1 use super::HeaderError; 2 3 /// Error when decoding two VLAN headers via a `std::io::Read` source. 4 /// 5 /// Requires crate feature `std`. 6 #[cfg(feature = "std")] 7 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 8 #[derive(Debug)] 9 pub enum HeaderReadError { 10 /// IO error was encountered while reading header. 11 Io(std::io::Error), 12 13 /// Error caused by the contents of the header. 14 Content(HeaderError), 15 } 16 17 #[cfg(feature = "std")] 18 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 19 impl HeaderReadError { 20 /// Returns the `std::io::Error` value if the `HeaderReadError` is `Io`. 21 /// Otherwise `None` is returned. 22 #[inline] io_error(self) -> Option<std::io::Error>23 pub fn io_error(self) -> Option<std::io::Error> { 24 use HeaderReadError::*; 25 match self { 26 Io(value) => Some(value), 27 _ => None, 28 } 29 } 30 31 /// Returns the `err::double_vlan::HeaderError` value if the `HeaderReadError` is `Content`. 32 /// Otherwise `None` is returned. 33 #[inline] content_error(self) -> Option<HeaderError>34 pub fn content_error(self) -> Option<HeaderError> { 35 use HeaderReadError::*; 36 match self { 37 Content(value) => Some(value), 38 _ => None, 39 } 40 } 41 } 42 43 #[cfg(feature = "std")] 44 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 45 impl core::fmt::Display for HeaderReadError { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result46 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 47 use HeaderReadError::*; 48 match self { 49 Io(err) => write!(f, "Double VLAN Header IO Error: {}", err), 50 Content(value) => value.fmt(f), 51 } 52 } 53 } 54 55 #[cfg(feature = "std")] 56 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 57 impl std::error::Error for HeaderReadError { source(&self) -> Option<&(dyn std::error::Error + 'static)>58 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 59 use HeaderReadError::*; 60 match self { 61 Io(err) => Some(err), 62 Content(err) => Some(err), 63 } 64 } 65 } 66 67 #[cfg(all(test, feature = "std"))] 68 mod test { 69 use super::{HeaderReadError::*, *}; 70 use alloc::format; 71 72 #[test] debug()73 fn debug() { 74 let err = HeaderError::NonVlanEtherType { 75 unexpected_ether_type: 1.into(), 76 }; 77 assert_eq!( 78 format!("Content({:?})", err.clone()), 79 format!("{:?}", Content(err)) 80 ); 81 } 82 83 #[test] fmt()84 fn fmt() { 85 { 86 let err = std::io::Error::new( 87 std::io::ErrorKind::UnexpectedEof, 88 "failed to fill whole buffer", 89 ); 90 assert_eq!( 91 format!("Double VLAN Header IO Error: {}", err), 92 format!("{}", Io(err)) 93 ); 94 } 95 { 96 let err = HeaderError::NonVlanEtherType { 97 unexpected_ether_type: 1.into(), 98 }; 99 assert_eq!(format!("{}", &err), format!("{}", Content(err.clone()))); 100 } 101 } 102 103 #[test] source()104 fn source() { 105 use std::error::Error; 106 assert!(Io(std::io::Error::new( 107 std::io::ErrorKind::UnexpectedEof, 108 "failed to fill whole buffer", 109 )) 110 .source() 111 .is_some()); 112 assert!(Content(HeaderError::NonVlanEtherType { 113 unexpected_ether_type: 1.into() 114 }) 115 .source() 116 .is_some()); 117 } 118 119 #[test] io_error()120 fn io_error() { 121 assert!(Io(std::io::Error::new( 122 std::io::ErrorKind::UnexpectedEof, 123 "failed to fill whole buffer", 124 )) 125 .io_error() 126 .is_some()); 127 assert!(Content(HeaderError::NonVlanEtherType { 128 unexpected_ether_type: 1.into() 129 }) 130 .io_error() 131 .is_none()); 132 } 133 134 #[test] content_error()135 fn content_error() { 136 assert_eq!( 137 None, 138 Io(std::io::Error::new( 139 std::io::ErrorKind::UnexpectedEof, 140 "failed to fill whole buffer", 141 )) 142 .content_error() 143 ); 144 { 145 let err = HeaderError::NonVlanEtherType { 146 unexpected_ether_type: 1.into(), 147 }; 148 assert_eq!(Some(err.clone()), Content(err.clone()).content_error()); 149 } 150 } 151 } 152