1 use super::HeaderError; 2 use crate::err::LenError; 3 4 /// Error when decoding Linux Cooked Capture v1 (SLL) 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::LinuxSllHeader, 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::LinuxSllHeader, 74 len: 2, 75 len_source: LenSource::Slice, 76 layer_start_offset: 203 77 }) 78 ); 79 assert_eq!( 80 Content(HeaderError::UnsupportedPacketTypeField { packet_type: 0 }) 81 .add_slice_offset(200), 82 Content(HeaderError::UnsupportedPacketTypeField { packet_type: 0 }) 83 ); 84 } 85 86 #[test] debug()87 fn debug() { 88 let err = HeaderError::UnsupportedPacketTypeField { packet_type: 0 }; 89 assert_eq!( 90 format!("Content({:?})", err.clone()), 91 format!("{:?}", Content(err)) 92 ); 93 } 94 95 #[test] clone_eq_hash()96 fn clone_eq_hash() { 97 let err = Content(HeaderError::UnsupportedPacketTypeField { packet_type: 0 }); 98 assert_eq!(err, err.clone()); 99 let hash_a = { 100 let mut hasher = DefaultHasher::new(); 101 err.hash(&mut hasher); 102 hasher.finish() 103 }; 104 let hash_b = { 105 let mut hasher = DefaultHasher::new(); 106 err.clone().hash(&mut hasher); 107 hasher.finish() 108 }; 109 assert_eq!(hash_a, hash_b); 110 } 111 112 #[test] fmt()113 fn fmt() { 114 { 115 let err = LenError { 116 required_len: 1, 117 layer: Layer::LinuxSllHeader, 118 len: 2, 119 len_source: LenSource::Slice, 120 layer_start_offset: 3, 121 }; 122 assert_eq!(format!("{}", &err), format!("{}", Len(err))); 123 } 124 { 125 let err = HeaderError::UnsupportedPacketTypeField { packet_type: 0 }; 126 assert_eq!(format!("{}", &err), format!("{}", Content(err.clone()))); 127 } 128 } 129 130 #[cfg(feature = "std")] 131 #[test] source()132 fn source() { 133 assert!(Len(LenError { 134 required_len: 1, 135 layer: Layer::LinuxSllHeader, 136 len: 2, 137 len_source: LenSource::Slice, 138 layer_start_offset: 3 139 }) 140 .source() 141 .is_some()); 142 assert!( 143 Content(HeaderError::UnsupportedPacketTypeField { packet_type: 0 }) 144 .source() 145 .is_some() 146 ); 147 } 148 } 149