1 #[cfg(feature = "std")] 2 use crate::err::{ipv4_exts, ipv6_exts}; 3 4 /// Error when writing IPv4 extension headers. 5 #[cfg(feature = "std")] 6 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 7 #[derive(Debug)] 8 pub enum HeadersWriteError { 9 /// IO error encountered while writing. 10 Io(std::io::Error), 11 /// IPv4 extensions can not be serialized (e.g. order 12 /// is not determinable as headers are never referenced). 13 Ipv4Exts(ipv4_exts::ExtsWalkError), 14 /// IPv6 extensions can not be serialized (e.g. order 15 /// is not determinable as headers are never referenced). 16 Ipv6Exts(ipv6_exts::ExtsWalkError), 17 } 18 19 #[cfg(feature = "std")] 20 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 21 impl HeadersWriteError { 22 /// Returns a reference to the [`std::io::Error`] if the value is an `Io`. io(&self) -> Option<&std::io::Error>23 pub fn io(&self) -> Option<&std::io::Error> { 24 match self { 25 HeadersWriteError::Io(err) => Some(err), 26 _ => None, 27 } 28 } 29 30 /// Returns a reference to the [`crate::err::ipv4_exts::ExtsWalkError`] 31 /// if the value is an `Ipv4Exts`. ipv4_exts(&self) -> Option<&ipv4_exts::ExtsWalkError>32 pub fn ipv4_exts(&self) -> Option<&ipv4_exts::ExtsWalkError> { 33 match self { 34 HeadersWriteError::Ipv4Exts(err) => Some(err), 35 _ => None, 36 } 37 } 38 39 /// Returns a reference to the [`crate::err::ipv6_exts::ExtsWalkError`] 40 /// if the value is an `Ipv6Exts`. ipv6_exts(&self) -> Option<&ipv6_exts::ExtsWalkError>41 pub fn ipv6_exts(&self) -> Option<&ipv6_exts::ExtsWalkError> { 42 match self { 43 HeadersWriteError::Ipv6Exts(err) => Some(err), 44 _ => None, 45 } 46 } 47 } 48 49 #[cfg(feature = "std")] 50 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 51 impl core::fmt::Display for HeadersWriteError { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result52 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 53 use HeadersWriteError::*; 54 match self { 55 Io(err) => err.fmt(f), 56 Ipv4Exts(err) => err.fmt(f), 57 Ipv6Exts(err) => err.fmt(f), 58 } 59 } 60 } 61 62 #[cfg(feature = "std")] 63 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 64 impl std::error::Error for HeadersWriteError { source(&self) -> Option<&(dyn std::error::Error + 'static)>65 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 66 use HeadersWriteError::*; 67 match self { 68 Io(ref err) => Some(err), 69 Ipv4Exts(ref err) => Some(err), 70 Ipv6Exts(ref err) => Some(err), 71 } 72 } 73 } 74 75 #[cfg(test)] 76 mod tests { 77 use super::{HeadersWriteError::*, *}; 78 use crate::*; 79 use alloc::format; 80 use std::error::Error; 81 82 #[test] io()83 fn io() { 84 assert!(Io(std::io::Error::new( 85 std::io::ErrorKind::UnexpectedEof, 86 "failed to fill whole buffer", 87 )) 88 .io() 89 .is_some()); 90 assert!(Ipv4Exts(ipv4_exts::ExtsWalkError::ExtNotReferenced { 91 missing_ext: IpNumber::AUTHENTICATION_HEADER, 92 }) 93 .io() 94 .is_none()); 95 } 96 97 #[test] ipv4_exts()98 fn ipv4_exts() { 99 assert!(Io(std::io::Error::new( 100 std::io::ErrorKind::UnexpectedEof, 101 "failed to fill whole buffer", 102 )) 103 .ipv4_exts() 104 .is_none()); 105 { 106 let err = ipv4_exts::ExtsWalkError::ExtNotReferenced { 107 missing_ext: IpNumber::AUTHENTICATION_HEADER, 108 }; 109 assert_eq!(Some(&err), Ipv4Exts(err.clone()).ipv4_exts()); 110 } 111 } 112 113 #[test] ipv6_exts()114 fn ipv6_exts() { 115 assert!(Io(std::io::Error::new( 116 std::io::ErrorKind::UnexpectedEof, 117 "failed to fill whole buffer", 118 )) 119 .ipv6_exts() 120 .is_none()); 121 { 122 let err = ipv6_exts::ExtsWalkError::ExtNotReferenced { 123 missing_ext: IpNumber::AUTHENTICATION_HEADER, 124 }; 125 assert_eq!(Some(&err), Ipv6Exts(err.clone()).ipv6_exts()); 126 } 127 } 128 129 #[test] debug()130 fn debug() { 131 let err = ipv6_exts::ExtsWalkError::ExtNotReferenced { 132 missing_ext: IpNumber::AUTHENTICATION_HEADER, 133 }; 134 assert_eq!( 135 format!("Ipv6Exts({:?})", err.clone()), 136 format!("{:?}", Ipv6Exts(err)) 137 ); 138 } 139 140 #[test] fmt()141 fn fmt() { 142 { 143 let err = std::io::Error::new( 144 std::io::ErrorKind::UnexpectedEof, 145 "failed to fill whole buffer", 146 ); 147 assert_eq!(format!("{}", err), format!("{}", Io(err))); 148 } 149 { 150 let err = ipv4_exts::ExtsWalkError::ExtNotReferenced { 151 missing_ext: IpNumber::AUTHENTICATION_HEADER, 152 }; 153 assert_eq!(format!("{}", Ipv4Exts(err.clone())), format!("{}", err)); 154 } 155 { 156 let err = ipv6_exts::ExtsWalkError::ExtNotReferenced { 157 missing_ext: IpNumber::AUTHENTICATION_HEADER, 158 }; 159 assert_eq!(format!("{}", Ipv6Exts(err.clone())), format!("{}", err)); 160 } 161 } 162 163 #[cfg(feature = "std")] 164 #[test] source()165 fn source() { 166 assert!(Io(std::io::Error::new( 167 std::io::ErrorKind::UnexpectedEof, 168 "failed to fill whole buffer", 169 )) 170 .source() 171 .is_some()); 172 assert!(Ipv4Exts(ipv4_exts::ExtsWalkError::ExtNotReferenced { 173 missing_ext: IpNumber::AUTHENTICATION_HEADER, 174 }) 175 .source() 176 .is_some()); 177 assert!(Ipv6Exts(ipv6_exts::ExtsWalkError::ExtNotReferenced { 178 missing_ext: IpNumber::AUTHENTICATION_HEADER, 179 }) 180 .source() 181 .is_some()); 182 } 183 } 184