1 use crate::*; 2 3 /// Error when decoding the IP header part of a message. 4 #[derive(Clone, Debug, Eq, PartialEq, Hash)] 5 pub enum HeadersError { 6 /// Error in the IPv4 or IPv6 header. 7 Ip(err::ip::HeaderError), 8 9 /// Error in the IPv4 extension headers (only authentication header). 10 Ipv4Ext(err::ip_auth::HeaderError), 11 12 /// Error in the IPv6 extension headers. 13 Ipv6Ext(err::ipv6_exts::HeaderError), 14 } 15 16 impl core::fmt::Display for HeadersError { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result17 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 18 use HeadersError::*; 19 match self { 20 Ip(err) => err.fmt(f), 21 Ipv4Ext(err) => err.fmt(f), 22 Ipv6Ext(err) => err.fmt(f), 23 } 24 } 25 } 26 27 #[cfg(feature = "std")] 28 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 29 impl std::error::Error for HeadersError { source(&self) -> Option<&(dyn std::error::Error + 'static)>30 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 31 use HeadersError::*; 32 match self { 33 Ip(err) => Some(err), 34 Ipv4Ext(err) => Some(err), 35 Ipv6Ext(err) => Some(err), 36 } 37 } 38 } 39 40 #[cfg(test)] 41 mod tests { 42 use super::{super::HeaderError::*, HeadersError::*, *}; 43 use alloc::format; 44 use std::{ 45 collections::hash_map::DefaultHasher, 46 error::Error, 47 hash::{Hash, Hasher}, 48 }; 49 50 #[test] debug()51 fn debug() { 52 assert_eq!( 53 "Ip(UnsupportedIpVersion { version_number: 6 })", 54 format!("{:?}", Ip(UnsupportedIpVersion { version_number: 6 })) 55 ); 56 } 57 58 #[test] clone_eq_hash()59 fn clone_eq_hash() { 60 let err = Ip(UnsupportedIpVersion { version_number: 6 }); 61 assert_eq!(err, err.clone()); 62 let hash_a = { 63 let mut hasher = DefaultHasher::new(); 64 err.hash(&mut hasher); 65 hasher.finish() 66 }; 67 let hash_b = { 68 let mut hasher = DefaultHasher::new(); 69 err.clone().hash(&mut hasher); 70 hasher.finish() 71 }; 72 assert_eq!(hash_a, hash_b); 73 } 74 75 #[test] fmt()76 fn fmt() { 77 assert_eq!( 78 "IP Header Error: Encountered '1' as IP version number in the IP header (only '4' or '6' are supported).", 79 format!("{}", UnsupportedIpVersion{ version_number: 1 }) 80 ); 81 assert_eq!( 82 "IPv4 Header Error: The 'internet header length' value '2' present in the IPv4 header is smaller than the minimum size of an IPv4 header. The minimum allowed value is '5'.", 83 format!("{}", Ipv4HeaderLengthSmallerThanHeader{ ihl: 2 }) 84 ); 85 { 86 let err = err::ip_auth::HeaderError::ZeroPayloadLen; 87 assert_eq!(format!("{}", Ipv4Ext(err.clone())), format!("{}", err)); 88 } 89 { 90 let err = err::ipv6_exts::HeaderError::HopByHopNotAtStart; 91 assert_eq!(format!("{}", Ipv6Ext(err.clone())), format!("{}", err)); 92 } 93 } 94 95 #[cfg(feature = "std")] 96 #[test] source()97 fn source() { 98 { 99 let values = [ 100 UnsupportedIpVersion { version_number: 0 }, 101 Ipv4HeaderLengthSmallerThanHeader { ihl: 0 }, 102 ]; 103 for v in values { 104 assert!(v.source().is_none()); 105 } 106 } 107 { 108 let values = [ 109 Ipv4Ext(err::ip_auth::HeaderError::ZeroPayloadLen), 110 Ipv6Ext(err::ipv6_exts::HeaderError::HopByHopNotAtStart), 111 ]; 112 for v in values { 113 assert!(v.source().is_some()); 114 } 115 } 116 } 117 } 118