• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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