1 use super::HeaderError; 2 use crate::err::LenError; 3 4 /// Error when decoding IPv6 extension headers via a `std::io::Read` source. 5 #[cfg(feature = "std")] 6 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 7 #[derive(Debug)] 8 pub enum HeaderLimitedReadError { 9 /// IO error was encountered while reading header. 10 Io(std::io::Error), 11 12 /// Error when parsing had to be aborted because a 13 /// length limit specified by an upper layer has been 14 /// exceeded. 15 Len(LenError), 16 17 /// Error caused by the contents of the header. 18 Content(HeaderError), 19 } 20 21 #[cfg(feature = "std")] 22 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 23 impl HeaderLimitedReadError { 24 /// Returns the [`std::io::Error`] value if the [`HeaderLimitedReadError`] is `Io`. 25 /// Otherwise `None` is returned. 26 #[inline] io(self) -> Option<std::io::Error>27 pub fn io(self) -> Option<std::io::Error> { 28 use HeaderLimitedReadError::*; 29 match self { 30 Io(value) => Some(value), 31 _ => None, 32 } 33 } 34 35 /// Returns the [`crate::err::LenError`] value if it is of value `Len`. 36 /// Otherwise `None` is returned. 37 #[inline] len(self) -> Option<LenError>38 pub fn len(self) -> Option<LenError> { 39 use HeaderLimitedReadError::*; 40 match self { 41 Len(value) => Some(value), 42 _ => None, 43 } 44 } 45 46 /// Returns the [`crate::err::ip_auth::HeaderError`] value if it is of value `Content`. 47 /// Otherwise `None` is returned. 48 #[inline] content(self) -> Option<HeaderError>49 pub fn content(self) -> Option<HeaderError> { 50 use HeaderLimitedReadError::*; 51 match self { 52 Content(value) => Some(value), 53 _ => None, 54 } 55 } 56 } 57 58 #[cfg(feature = "std")] 59 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 60 impl core::fmt::Display for HeaderLimitedReadError { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result61 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 62 use HeaderLimitedReadError::*; 63 match self { 64 Io(err) => write!(f, "IPv6 Extension Header IO Error: {}", err), 65 Len(err) => err.fmt(f), 66 Content(err) => err.fmt(f), 67 } 68 } 69 } 70 71 #[cfg(feature = "std")] 72 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 73 impl std::error::Error for HeaderLimitedReadError { source(&self) -> Option<&(dyn std::error::Error + 'static)>74 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 75 use HeaderLimitedReadError::*; 76 match self { 77 Io(err) => Some(err), 78 Len(err) => Some(err), 79 Content(err) => Some(err), 80 } 81 } 82 } 83 84 #[cfg(all(test, feature = "std"))] 85 mod test { 86 use crate::{err::Layer, LenSource}; 87 88 use super::{HeaderLimitedReadError::*, *}; 89 use alloc::format; 90 91 #[test] debug()92 fn debug() { 93 let err = HeaderError::HopByHopNotAtStart; 94 assert_eq!( 95 format!("Content({:?})", err.clone()), 96 format!("{:?}", Content(err)) 97 ); 98 } 99 100 #[test] fmt()101 fn fmt() { 102 { 103 let err = std::io::Error::new( 104 std::io::ErrorKind::UnexpectedEof, 105 "failed to fill whole buffer", 106 ); 107 assert_eq!( 108 format!("IPv6 Extension Header IO Error: {}", err), 109 format!("{}", Io(err)) 110 ); 111 } 112 { 113 let err = LenError { 114 required_len: 2, 115 len: 1, 116 len_source: LenSource::Slice, 117 layer: Layer::IpAuthHeader, 118 layer_start_offset: 3, 119 }; 120 assert_eq!(format!("{}", &err), format!("{}", Len(err.clone()))); 121 } 122 { 123 let err = HeaderError::HopByHopNotAtStart; 124 assert_eq!(format!("{}", &err), format!("{}", Content(err.clone()))); 125 } 126 } 127 128 #[test] source()129 fn source() { 130 use std::error::Error; 131 assert!(Io(std::io::Error::new( 132 std::io::ErrorKind::UnexpectedEof, 133 "failed to fill whole buffer", 134 )) 135 .source() 136 .is_some()); 137 assert!(Len(LenError { 138 required_len: 2, 139 len: 1, 140 len_source: LenSource::Slice, 141 layer: Layer::IpAuthHeader, 142 layer_start_offset: 3, 143 }) 144 .source() 145 .is_some()); 146 assert!(Content(HeaderError::HopByHopNotAtStart).source().is_some()); 147 } 148 149 #[test] io()150 fn io() { 151 assert!(Io(std::io::Error::new( 152 std::io::ErrorKind::UnexpectedEof, 153 "failed to fill whole buffer", 154 )) 155 .io() 156 .is_some()); 157 assert!(Content(HeaderError::HopByHopNotAtStart).io().is_none()); 158 } 159 160 #[test] len()161 fn len() { 162 assert_eq!( 163 None, 164 Io(std::io::Error::new( 165 std::io::ErrorKind::UnexpectedEof, 166 "failed to fill whole buffer", 167 )) 168 .len() 169 ); 170 { 171 let err = LenError { 172 required_len: 2, 173 len: 1, 174 len_source: LenSource::Slice, 175 layer: Layer::IpAuthHeader, 176 layer_start_offset: 3, 177 }; 178 assert_eq!(Some(err.clone()), Len(err.clone()).len()); 179 } 180 } 181 182 #[test] content()183 fn content() { 184 assert_eq!( 185 None, 186 Io(std::io::Error::new( 187 std::io::ErrorKind::UnexpectedEof, 188 "failed to fill whole buffer", 189 )) 190 .content() 191 ); 192 { 193 let err = HeaderError::HopByHopNotAtStart; 194 assert_eq!(Some(err.clone()), Content(err.clone()).content()); 195 } 196 } 197 } 198