1 use crate::err::{ip_auth, ipv4, LenError}; 2 3 /// Errors that can occur when slicing the IPv4 part of a packet. 4 #[derive(Clone, Debug, Eq, PartialEq, Hash)] 5 pub enum SliceError { 6 /// Length related errors (e.g. not enough data in slice). 7 Len(LenError), 8 9 /// Error while slicing the header. 10 Header(ipv4::HeaderError), 11 12 /// Error while slicing an ipv4 extension header. 13 Exts(ip_auth::HeaderError), 14 } 15 16 impl core::fmt::Display for SliceError { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result17 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 18 use SliceError::*; 19 match self { 20 Len(value) => value.fmt(f), 21 Header(err) => err.fmt(f), 22 Exts(value) => value.fmt(f), 23 } 24 } 25 } 26 27 #[cfg(feature = "std")] 28 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 29 impl std::error::Error for SliceError { source(&self) -> Option<&(dyn std::error::Error + 'static)>30 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 31 use SliceError::*; 32 match self { 33 Len(err) => Some(err), 34 Header(err) => Some(err), 35 Exts(err) => Some(err), 36 } 37 } 38 } 39 40 #[cfg(test)] 41 mod tests { 42 use super::{super::HeaderError, SliceError::*, *}; 43 use crate::{err::Layer, LenSource}; 44 use alloc::format; 45 use std::{ 46 collections::hash_map::DefaultHasher, 47 error::Error, 48 hash::{Hash, Hasher}, 49 }; 50 51 #[test] debug()52 fn debug() { 53 let err = HeaderError::UnexpectedVersion { version_number: 6 }; 54 assert_eq!( 55 format!("Header({:?})", err.clone()), 56 format!("{:?}", Header(err)) 57 ); 58 } 59 60 #[test] clone_eq_hash()61 fn clone_eq_hash() { 62 let err = Header(HeaderError::UnexpectedVersion { version_number: 6 }); 63 assert_eq!(err, err.clone()); 64 let hash_a = { 65 let mut hasher = DefaultHasher::new(); 66 err.hash(&mut hasher); 67 hasher.finish() 68 }; 69 let hash_b = { 70 let mut hasher = DefaultHasher::new(); 71 err.clone().hash(&mut hasher); 72 hasher.finish() 73 }; 74 assert_eq!(hash_a, hash_b); 75 } 76 77 #[test] fmt()78 fn fmt() { 79 // len 80 { 81 let err = LenError { 82 required_len: 1, 83 layer: Layer::Ipv4Packet, 84 len: 2, 85 len_source: LenSource::Slice, 86 layer_start_offset: 3, 87 }; 88 assert_eq!(format!("{}", &err), format!("{}", Len(err))); 89 } 90 // header 91 { 92 let err = HeaderError::UnexpectedVersion { version_number: 6 }; 93 assert_eq!(format!("{}", &err), format!("{}", Header(err.clone()))); 94 } 95 // extensions 96 { 97 let err = ip_auth::HeaderError::ZeroPayloadLen; 98 assert_eq!(format!("{}", &err), format!("{}", Exts(err.clone()))); 99 } 100 } 101 102 #[cfg(feature = "std")] 103 #[test] source()104 fn source() { 105 assert!(Len(LenError { 106 required_len: 1, 107 layer: Layer::Ipv4Packet, 108 len: 2, 109 len_source: LenSource::Slice, 110 layer_start_offset: 3 111 }) 112 .source() 113 .is_some()); 114 assert!(Header(HeaderError::UnexpectedVersion { version_number: 6 }) 115 .source() 116 .is_some()); 117 assert!(Exts(ip_auth::HeaderError::ZeroPayloadLen) 118 .source() 119 .is_some()); 120 } 121 } 122