1 use super::HeadersError; 2 use crate::err::LenError; 3 4 /// Error when decoding an IP header 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 the header. 12 Content(HeadersError), 13 } 14 15 impl HeadersSliceError { 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 HeadersSliceError::*; 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 HeadersSliceError { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result28 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 29 use HeadersSliceError::*; 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 HeadersSliceError { source(&self) -> Option<&(dyn std::error::Error + 'static)>40 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 41 use HeadersSliceError::*; 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::{ 52 super::{HeaderError::*, HeadersError::*}, 53 HeadersSliceError::*, 54 *, 55 }; 56 use crate::{err::Layer, LenSource}; 57 use alloc::format; 58 use std::{ 59 collections::hash_map::DefaultHasher, 60 error::Error, 61 hash::{Hash, Hasher}, 62 }; 63 64 #[test] add_slice_offset()65 fn add_slice_offset() { 66 use HeadersSliceError::*; 67 assert_eq!( 68 Len(LenError { 69 required_len: 1, 70 layer: Layer::Icmpv4, 71 len: 2, 72 len_source: LenSource::Slice, 73 layer_start_offset: 3 74 }) 75 .add_slice_offset(200), 76 Len(LenError { 77 required_len: 1, 78 layer: Layer::Icmpv4, 79 len: 2, 80 len_source: LenSource::Slice, 81 layer_start_offset: 203 82 }) 83 ); 84 assert_eq!( 85 Content(Ip(UnsupportedIpVersion { version_number: 1 })).add_slice_offset(200), 86 Content(Ip(UnsupportedIpVersion { version_number: 1 })) 87 ); 88 } 89 90 #[test] debug()91 fn debug() { 92 let err = Ip(UnsupportedIpVersion { version_number: 6 }); 93 assert_eq!( 94 format!("Content({:?})", err.clone()), 95 format!("{:?}", Content(err)) 96 ); 97 } 98 99 #[test] clone_eq_hash()100 fn clone_eq_hash() { 101 let err = Content(Ip(UnsupportedIpVersion { version_number: 6 })); 102 assert_eq!(err, err.clone()); 103 let hash_a = { 104 let mut hasher = DefaultHasher::new(); 105 err.hash(&mut hasher); 106 hasher.finish() 107 }; 108 let hash_b = { 109 let mut hasher = DefaultHasher::new(); 110 err.clone().hash(&mut hasher); 111 hasher.finish() 112 }; 113 assert_eq!(hash_a, hash_b); 114 } 115 116 #[test] fmt()117 fn fmt() { 118 { 119 let err = LenError { 120 required_len: 1, 121 layer: Layer::Icmpv4, 122 len: 2, 123 len_source: LenSource::Slice, 124 layer_start_offset: 3, 125 }; 126 assert_eq!(format!("{}", &err), format!("{}", Len(err))); 127 } 128 { 129 let err = Ip(UnsupportedIpVersion { version_number: 6 }); 130 assert_eq!(format!("{}", &err), format!("{}", Content(err.clone()))); 131 } 132 } 133 134 #[cfg(feature = "std")] 135 #[test] source()136 fn source() { 137 assert!(Len(LenError { 138 required_len: 1, 139 layer: Layer::Icmpv4, 140 len: 2, 141 len_source: LenSource::Slice, 142 layer_start_offset: 3 143 }) 144 .source() 145 .is_some()); 146 assert!(Content(Ip(UnsupportedIpVersion { version_number: 6 })) 147 .source() 148 .is_some()); 149 } 150 } 151