1 #[cfg(feature = "std")] 2 use super::ExtsWalkError; 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 HeaderWriteError { 9 /// IO error encountered while writing. 10 Io(std::io::Error), 11 /// Data was not serializable because of its content. 12 Content(ExtsWalkError), 13 } 14 15 #[cfg(feature = "std")] 16 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 17 impl HeaderWriteError { 18 /// Returns a reference to the [`std::io::Error`] if the value is an [`HeaderWriteError::Io`]. io(&self) -> Option<&std::io::Error>19 pub fn io(&self) -> Option<&std::io::Error> { 20 match self { 21 HeaderWriteError::Io(err) => Some(err), 22 HeaderWriteError::Content(_) => None, 23 } 24 } 25 26 /// Returns a reference to the [`crate::err::ipv4_exts::ExtsWalkError`] if the value is an [`HeaderWriteError::Content`]. content(&self) -> Option<&ExtsWalkError>27 pub fn content(&self) -> Option<&ExtsWalkError> { 28 match self { 29 HeaderWriteError::Io(_) => None, 30 HeaderWriteError::Content(err) => Some(err), 31 } 32 } 33 } 34 35 #[cfg(feature = "std")] 36 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 37 impl core::fmt::Display for HeaderWriteError { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result38 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 39 use HeaderWriteError::*; 40 match self { 41 Io(err) => err.fmt(f), 42 Content(err) => err.fmt(f), 43 } 44 } 45 } 46 47 #[cfg(feature = "std")] 48 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 49 impl std::error::Error for HeaderWriteError { source(&self) -> Option<&(dyn std::error::Error + 'static)>50 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 51 use HeaderWriteError::*; 52 match self { 53 Io(ref err) => Some(err), 54 Content(ref err) => Some(err), 55 } 56 } 57 } 58 59 #[cfg(test)] 60 mod tests { 61 use super::{ExtsWalkError::*, HeaderWriteError::*}; 62 use crate::*; 63 use alloc::format; 64 use std::error::Error; 65 66 #[test] io()67 fn io() { 68 assert!(Io(std::io::Error::new( 69 std::io::ErrorKind::UnexpectedEof, 70 "failed to fill whole buffer", 71 )) 72 .io() 73 .is_some()); 74 assert!(Content(ExtNotReferenced { 75 missing_ext: IpNumber::AUTHENTICATION_HEADER, 76 }) 77 .io() 78 .is_none()); 79 } 80 81 #[test] content()82 fn content() { 83 assert!(Io(std::io::Error::new( 84 std::io::ErrorKind::UnexpectedEof, 85 "failed to fill whole buffer", 86 )) 87 .content() 88 .is_none()); 89 { 90 let err = ExtNotReferenced { 91 missing_ext: IpNumber::AUTHENTICATION_HEADER, 92 }; 93 assert_eq!(Some(&err), Content(err.clone()).content()); 94 } 95 } 96 97 #[test] debug()98 fn debug() { 99 let err = ExtNotReferenced { 100 missing_ext: IpNumber::AUTHENTICATION_HEADER, 101 }; 102 assert_eq!( 103 format!("Content({:?})", err.clone()), 104 format!("{:?}", Content(err)) 105 ); 106 } 107 108 #[test] fmt()109 fn fmt() { 110 { 111 let err = std::io::Error::new( 112 std::io::ErrorKind::UnexpectedEof, 113 "failed to fill whole buffer", 114 ); 115 assert_eq!(format!("{}", err), format!("{}", Io(err))); 116 } 117 { 118 let err = ExtNotReferenced { 119 missing_ext: IpNumber::AUTHENTICATION_HEADER, 120 }; 121 assert_eq!(format!("{}", Content(err.clone())), format!("{}", err)); 122 } 123 } 124 125 #[cfg(feature = "std")] 126 #[test] source()127 fn source() { 128 assert!(Io(std::io::Error::new( 129 std::io::ErrorKind::UnexpectedEof, 130 "failed to fill whole buffer", 131 )) 132 .source() 133 .is_some()); 134 assert!(Content(ExtNotReferenced { 135 missing_ext: IpNumber::AUTHENTICATION_HEADER, 136 }) 137 .source() 138 .is_some()); 139 } 140 } 141