1 use super::HeaderError; 2 use crate::err::LenError; 3 4 /// Error when decoding a TCP 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 match self { 42 HeaderSliceError::Len(err) => Some(err), 43 HeaderSliceError::Content(err) => Some(err), 44 } 45 } 46 } 47 48 #[cfg(test)] 49 mod tests { 50 use super::{HeaderSliceError::*, *}; 51 use crate::{err::Layer, LenSource}; 52 use alloc::format; 53 use std::{ 54 collections::hash_map::DefaultHasher, 55 error::Error, 56 hash::{Hash, Hasher}, 57 }; 58 59 #[test] add_slice_offset()60 fn add_slice_offset() { 61 use HeaderSliceError::*; 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::DataOffsetTooSmall { data_offset: 1 }).add_slice_offset(200), 81 Content(HeaderError::DataOffsetTooSmall { data_offset: 1 }) 82 ); 83 } 84 85 #[test] debug()86 fn debug() { 87 let err = HeaderError::DataOffsetTooSmall { data_offset: 1 }; 88 assert_eq!( 89 format!("Content({:?})", err.clone()), 90 format!("{:?}", Content(err)) 91 ); 92 } 93 94 #[test] clone_eq_hash()95 fn clone_eq_hash() { 96 let err = Content(HeaderError::DataOffsetTooSmall { data_offset: 1 }); 97 assert_eq!(err, err.clone()); 98 let hash_a = { 99 let mut hasher = DefaultHasher::new(); 100 err.hash(&mut hasher); 101 hasher.finish() 102 }; 103 let hash_b = { 104 let mut hasher = DefaultHasher::new(); 105 err.clone().hash(&mut hasher); 106 hasher.finish() 107 }; 108 assert_eq!(hash_a, hash_b); 109 } 110 111 #[test] fmt()112 fn fmt() { 113 { 114 let err = LenError { 115 required_len: 1, 116 layer: Layer::Icmpv4, 117 len: 2, 118 len_source: LenSource::Slice, 119 layer_start_offset: 3, 120 }; 121 assert_eq!(format!("{}", &err), format!("{}", Len(err))); 122 } 123 { 124 let err = HeaderError::DataOffsetTooSmall { data_offset: 1 }; 125 assert_eq!(format!("{}", &err), format!("{}", Content(err.clone()))); 126 } 127 } 128 129 #[cfg(feature = "std")] 130 #[test] source()131 fn source() { 132 assert!(Len(LenError { 133 required_len: 1, 134 layer: Layer::Icmpv4, 135 len: 2, 136 len_source: LenSource::Slice, 137 layer_start_offset: 3 138 }) 139 .source() 140 .is_some()); 141 assert!(Content(HeaderError::DataOffsetTooSmall { data_offset: 1 }) 142 .source() 143 .is_some()); 144 } 145 } 146