1 use crate::err::{ipv6, ipv6_exts, LenError}; 2 3 /// Errors that can occur when slicing the IPv6 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(ipv6::HeaderError), 11 12 /// Error while slicing an ipv6 extension header. 13 Exts(ipv6_exts::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::{ 44 err::{ip_auth, Layer}, 45 LenSource, 46 }; 47 use alloc::format; 48 use std::{ 49 collections::hash_map::DefaultHasher, 50 error::Error, 51 hash::{Hash, Hasher}, 52 }; 53 54 #[test] debug()55 fn debug() { 56 let err = HeaderError::UnexpectedVersion { version_number: 6 }; 57 assert_eq!( 58 format!("Header({:?})", err.clone()), 59 format!("{:?}", Header(err)) 60 ); 61 } 62 63 #[test] clone_eq_hash()64 fn clone_eq_hash() { 65 let err = Header(HeaderError::UnexpectedVersion { version_number: 6 }); 66 assert_eq!(err, err.clone()); 67 let hash_a = { 68 let mut hasher = DefaultHasher::new(); 69 err.hash(&mut hasher); 70 hasher.finish() 71 }; 72 let hash_b = { 73 let mut hasher = DefaultHasher::new(); 74 err.clone().hash(&mut hasher); 75 hasher.finish() 76 }; 77 assert_eq!(hash_a, hash_b); 78 } 79 80 #[test] fmt()81 fn fmt() { 82 // len 83 { 84 let err = LenError { 85 required_len: 1, 86 layer: Layer::Ipv6Packet, 87 len: 2, 88 len_source: LenSource::Slice, 89 layer_start_offset: 3, 90 }; 91 assert_eq!(format!("{}", &err), format!("{}", Len(err))); 92 } 93 // header 94 { 95 let err = HeaderError::UnexpectedVersion { version_number: 6 }; 96 assert_eq!(format!("{}", &err), format!("{}", Header(err.clone()))); 97 } 98 // extensions 99 { 100 let err = ipv6_exts::HeaderError::IpAuth(ip_auth::HeaderError::ZeroPayloadLen); 101 assert_eq!(format!("{}", &err), format!("{}", Exts(err.clone()))); 102 } 103 } 104 105 #[cfg(feature = "std")] 106 #[test] source()107 fn source() { 108 assert!(Len(LenError { 109 required_len: 1, 110 layer: Layer::Ipv4Packet, 111 len: 2, 112 len_source: LenSource::Slice, 113 layer_start_offset: 3 114 }) 115 .source() 116 .is_some()); 117 assert!(Header(HeaderError::UnexpectedVersion { version_number: 6 }) 118 .source() 119 .is_some()); 120 assert!(Exts(ipv6_exts::HeaderError::IpAuth( 121 ip_auth::HeaderError::ZeroPayloadLen 122 )) 123 .source() 124 .is_some()); 125 } 126 } 127