1 use crate::IpNumber; 2 3 /// Errors in content of IPv6 header extensions that prevent serialization. 4 #[derive(Clone, Debug, Eq, PartialEq, Hash)] 5 pub enum ExtsWalkError { 6 /// Error when a hop-by-hop header is not referenced as the 7 /// first header after the ipv6 header but as a later extension 8 /// header. 9 HopByHopNotAtStart, 10 11 /// Error when a header in [`crate::Ipv6Extensions`] is never written 12 /// as it is never referenced by any of the other `next_header` 13 /// fields or the initial ip number. 14 ExtNotReferenced { 15 /// IpNumber of the header which was not referenced. 16 missing_ext: IpNumber, 17 }, 18 } 19 20 impl core::fmt::Display for ExtsWalkError { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result21 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 22 match self { 23 ExtsWalkError::HopByHopNotAtStart => 24 write!(f, "IPv6 extensions hop-by-hop is not located directly after the IPv6 header (required by IPv6)."), 25 ExtsWalkError::ExtNotReferenced{ missing_ext } => 26 write!(f, "IPv6 extensions '{:?}' is defined but is not referenced by any of the 'next_header' of the other extension headers or the IPv6 header.", missing_ext), 27 } 28 } 29 } 30 31 #[cfg(feature = "std")] 32 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 33 impl std::error::Error for ExtsWalkError { source(&self) -> Option<&(dyn std::error::Error + 'static)>34 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 35 None 36 } 37 } 38 39 #[cfg(test)] 40 mod tests { 41 use super::ExtsWalkError::*; 42 use crate::*; 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!("HopByHopNotAtStart", format!("{:?}", HopByHopNotAtStart)); 53 } 54 55 #[test] clone_eq_hash()56 fn clone_eq_hash() { 57 let err = HopByHopNotAtStart; 58 assert_eq!(err, err.clone()); 59 let hash_a = { 60 let mut hasher = DefaultHasher::new(); 61 err.hash(&mut hasher); 62 hasher.finish() 63 }; 64 let hash_b = { 65 let mut hasher = DefaultHasher::new(); 66 err.clone().hash(&mut hasher); 67 hasher.finish() 68 }; 69 assert_eq!(hash_a, hash_b); 70 } 71 72 #[test] fmt()73 fn fmt() { 74 assert_eq!( 75 "IPv6 extensions hop-by-hop is not located directly after the IPv6 header (required by IPv6).", 76 format!("{}", HopByHopNotAtStart) 77 ); 78 assert_eq!( 79 "IPv6 extensions '44 (IPv6-Frag - Fragment Header for IPv6)' is defined but is not referenced by any of the 'next_header' of the other extension headers or the IPv6 header.", 80 format!("{}", ExtNotReferenced{ missing_ext: IpNumber::IPV6_FRAGMENTATION_HEADER }) 81 ); 82 } 83 84 #[cfg(feature = "std")] 85 #[test] source()86 fn source() { 87 assert!(HopByHopNotAtStart.source().is_none()); 88 assert!(ExtNotReferenced { 89 missing_ext: IpNumber::IPV6_FRAGMENTATION_HEADER 90 } 91 .source() 92 .is_none()); 93 } 94 } 95