1 use super::HeaderError; 2 use crate::err::LenError; 3 4 /// Error when decoding a double VLAN header 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 27 impl core::fmt::Display for HeaderSliceError { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result28 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 29 use HeaderSliceError::*; 30 match self { 31 Len(err) => err.fmt(f), 32 Content(err) => err.fmt(f), 33 } 34 } 35 } 36 37 #[cfg(feature = "std")] 38 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 39 impl std::error::Error for HeaderSliceError { source(&self) -> Option<&(dyn std::error::Error + 'static)>40 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 41 use HeaderSliceError::*; 42 match self { 43 Len(err) => Some(err), 44 Content(err) => Some(err), 45 } 46 } 47 } 48 49 #[cfg(test)] 50 mod tests { 51 use super::{HeaderSliceError::*, *}; 52 use crate::{err::Layer, LenSource}; 53 use alloc::format; 54 use std::{ 55 collections::hash_map::DefaultHasher, 56 error::Error, 57 hash::{Hash, Hasher}, 58 }; 59 60 #[test] add_slice_offset()61 fn add_slice_offset() { 62 assert_eq!( 63 Len(LenError { 64 required_len: 1, 65 layer: Layer::Icmpv4, 66 len: 2, 67 len_source: LenSource::Slice, 68 layer_start_offset: 3 69 }) 70 .add_slice_offset(200), 71 Len(LenError { 72 required_len: 1, 73 layer: Layer::Icmpv4, 74 len: 2, 75 len_source: LenSource::Slice, 76 layer_start_offset: 203 77 }) 78 ); 79 assert_eq!( 80 Content(HeaderError::NonVlanEtherType { 81 unexpected_ether_type: 1.into() 82 }) 83 .add_slice_offset(200), 84 Content(HeaderError::NonVlanEtherType { 85 unexpected_ether_type: 1.into() 86 }) 87 ); 88 } 89 90 #[test] debug()91 fn debug() { 92 let err = HeaderError::NonVlanEtherType { 93 unexpected_ether_type: 1.into(), 94 }; 95 assert_eq!( 96 format!("Content({:?})", err.clone()), 97 format!("{:?}", Content(err)) 98 ); 99 } 100 101 #[test] clone_eq_hash()102 fn clone_eq_hash() { 103 let err = Content(HeaderError::NonVlanEtherType { 104 unexpected_ether_type: 1.into(), 105 }); 106 assert_eq!(err, err.clone()); 107 let hash_a = { 108 let mut hasher = DefaultHasher::new(); 109 err.hash(&mut hasher); 110 hasher.finish() 111 }; 112 let hash_b = { 113 let mut hasher = DefaultHasher::new(); 114 err.clone().hash(&mut hasher); 115 hasher.finish() 116 }; 117 assert_eq!(hash_a, hash_b); 118 } 119 120 #[test] fmt()121 fn fmt() { 122 { 123 let err = LenError { 124 required_len: 1, 125 layer: Layer::Icmpv4, 126 len: 2, 127 len_source: LenSource::Slice, 128 layer_start_offset: 3, 129 }; 130 assert_eq!(format!("{}", &err), format!("{}", Len(err))); 131 } 132 { 133 let err = HeaderError::NonVlanEtherType { 134 unexpected_ether_type: 1.into(), 135 }; 136 assert_eq!(format!("{}", &err), format!("{}", Content(err.clone()))); 137 } 138 } 139 140 #[cfg(feature = "std")] 141 #[test] source()142 fn source() { 143 assert!(Len(LenError { 144 required_len: 1, 145 layer: Layer::Icmpv4, 146 len: 2, 147 len_source: LenSource::Slice, 148 layer_start_offset: 3 149 }) 150 .source() 151 .is_some()); 152 assert!(Content(HeaderError::NonVlanEtherType { 153 unexpected_ether_type: 1.into() 154 }) 155 .source() 156 .is_some()); 157 } 158 } 159