etherparse/err/packet/
slice_error.rs

1use crate::*;
2
3/// Error when slicing an packet from downwards (both
4/// starting from ethernet or ip layer downwards).
5#[derive(Clone, Debug, Eq, PartialEq, Hash)]
6pub enum SliceError {
7    /// Length related errors (e.g. not enough data in slice).
8    Len(err::LenError),
9    /// Error when decoding an Linux SLL header.
10    LinuxSll(err::linux_sll::HeaderError),
11    /// Error when decoding starting at an IP header (v4 or v6).
12    Ip(err::ip::HeaderError),
13    /// Error when decoding an IPv4 header.
14    Ipv4(err::ipv4::HeaderError),
15    /// Error when decoding an IPv6 header.
16    Ipv6(err::ipv6::HeaderError),
17    /// Error when decoding an IPv4 extension header.
18    Ipv4Exts(err::ip_auth::HeaderError),
19    /// Error when decoding an IPv6 extension header.
20    Ipv6Exts(err::ipv6_exts::HeaderError),
21    /// Error when decoding a TCP header.
22    Tcp(err::tcp::HeaderError),
23}
24
25impl core::fmt::Display for SliceError {
26    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
27        use SliceError::*;
28
29        match self {
30            Len(err) => err.fmt(f),
31            LinuxSll(err) => err.fmt(f),
32            Ip(err) => err.fmt(f),
33            Ipv4(err) => err.fmt(f),
34            Ipv6(err) => err.fmt(f),
35            Ipv4Exts(err) => err.fmt(f),
36            Ipv6Exts(err) => err.fmt(f),
37            Tcp(err) => err.fmt(f),
38        }
39    }
40}
41
42#[cfg(feature = "std")]
43#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
44impl std::error::Error for SliceError {
45    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
46        use SliceError::*;
47        match self {
48            Len(err) => Some(err),
49            LinuxSll(err) => Some(err),
50            Ip(err) => Some(err),
51            Ipv4(err) => Some(err),
52            Ipv6(err) => Some(err),
53            Ipv4Exts(err) => Some(err),
54            Ipv6Exts(err) => Some(err),
55            Tcp(err) => Some(err),
56        }
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::{SliceError::*, *};
63    use crate::err::Layer;
64    use alloc::format;
65    use std::{
66        collections::hash_map::DefaultHasher,
67        error::Error,
68        hash::{Hash, Hasher},
69    };
70
71    #[test]
72    fn debug() {
73        let err = err::ipv4::HeaderError::UnexpectedVersion { version_number: 1 };
74        assert_eq!(
75            format!("Ipv4({:?})", err.clone()),
76            format!("{:?}", Ipv4(err))
77        );
78    }
79
80    #[test]
81    fn clone_eq_hash() {
82        let err = Ipv4(err::ipv4::HeaderError::UnexpectedVersion { version_number: 1 });
83        assert_eq!(err, err.clone());
84        let hash_a = {
85            let mut hasher = DefaultHasher::new();
86            err.hash(&mut hasher);
87            hasher.finish()
88        };
89        let hash_b = {
90            let mut hasher = DefaultHasher::new();
91            err.clone().hash(&mut hasher);
92            hasher.finish()
93        };
94        assert_eq!(hash_a, hash_b);
95    }
96
97    #[test]
98    fn fmt() {
99        // Len
100        {
101            let err = err::LenError {
102                required_len: 2,
103                len: 1,
104                len_source: LenSource::Slice,
105                layer: Layer::TcpHeader,
106                layer_start_offset: 3,
107            };
108            assert_eq!(format!("{}", err), format!("{}", Len(err)));
109        }
110
111        // Linux SLL Header
112        {
113            let err = err::linux_sll::HeaderError::UnsupportedArpHardwareId {
114                arp_hardware_type: ArpHardwareId::ADAPT,
115            };
116            assert_eq!(
117                format!("{}", err),
118                format!("{}", err::packet::SliceError::LinuxSll(err))
119            );
120        }
121
122        // IpHeader
123        {
124            let err = err::ip::HeaderError::UnsupportedIpVersion { version_number: 1 };
125            assert_eq!(
126                format!("{}", err),
127                format!("{}", err::packet::SliceError::Ip(err))
128            );
129        }
130
131        // Ipv4Header
132        {
133            let err = err::ipv4::HeaderError::UnexpectedVersion { version_number: 1 };
134            assert_eq!(format!("{}", err), format!("{}", Ipv4(err)));
135        }
136
137        // Ipv6Header
138        {
139            let err = err::ipv6::HeaderError::UnexpectedVersion { version_number: 1 };
140            assert_eq!(format!("{}", err), format!("{}", Ipv6(err)));
141        }
142
143        // Ipv4ExtHeader
144        {
145            let err = err::ip_auth::HeaderError::ZeroPayloadLen;
146            assert_eq!(format!("{}", err), format!("{}", Ipv4Exts(err)));
147        }
148
149        // Ipv6ExtHeader
150        {
151            let err = err::ipv6_exts::HeaderError::HopByHopNotAtStart;
152            assert_eq!(format!("{}", err), format!("{}", Ipv6Exts(err)));
153        };
154
155        // TcpHeader
156        {
157            let err = err::tcp::HeaderError::DataOffsetTooSmall { data_offset: 1 };
158            assert_eq!(format!("{}", err), format!("{}", Tcp(err)));
159        }
160    }
161
162    #[cfg(feature = "std")]
163    #[test]
164    fn source() {
165        // Len
166        {
167            let err = err::LenError {
168                required_len: 2,
169                len: 1,
170                len_source: LenSource::Slice,
171                layer: Layer::TcpHeader,
172                layer_start_offset: 3,
173            };
174            assert!(Len(err).source().is_some());
175        }
176
177        // IpHeaders
178        {
179            let err = err::linux_sll::HeaderError::UnsupportedArpHardwareId {
180                arp_hardware_type: ArpHardwareId::ETHERNET,
181            };
182            assert!(LinuxSll(err).source().is_some());
183        }
184
185        // IpHeaders
186        {
187            let err = err::ip::HeaderError::UnsupportedIpVersion { version_number: 1 };
188            assert!(Ip(err).source().is_some());
189        }
190
191        // Ipv4Header
192        {
193            let err = err::ipv4::HeaderError::UnexpectedVersion { version_number: 1 };
194            assert!(Ipv4(err).source().is_some());
195        }
196
197        // Ipv6Header
198        {
199            let err = err::ipv6::HeaderError::UnexpectedVersion { version_number: 1 };
200            assert!(Ipv6(err).source().is_some());
201        }
202
203        // Ipv4ExtHeader
204        {
205            let err = err::ip_auth::HeaderError::ZeroPayloadLen;
206            assert!(Ipv4Exts(err).source().is_some());
207        }
208
209        // Ipv6ExtHeader
210        {
211            let err = err::ipv6_exts::HeaderError::HopByHopNotAtStart;
212            assert!(Ipv6Exts(err).source().is_some());
213        };
214
215        // TcpHeader
216        {
217            let err = err::tcp::HeaderError::DataOffsetTooSmall { data_offset: 1 };
218            assert!(Tcp(err).source().is_some());
219        }
220    }
221}