1 use crate::{Ethernet2Header, LinuxSllHeader};
2 
3 /// The possible headers on the link layer
4 #[derive(Clone, Debug, Eq, PartialEq)]
5 pub enum LinkHeader {
6     LinuxSll(LinuxSllHeader),
7     Ethernet2(Ethernet2Header),
8 }
9 
10 impl LinkHeader {
11     /// Returns `Option::Some` containing the `Ethernet2Header` if self has the
12     /// value Ethernet2. Otherwise `Option::None` is returned.
ethernet2(self) -> Option<Ethernet2Header>13     pub fn ethernet2(self) -> Option<Ethernet2Header> {
14         use crate::LinkHeader::*;
15         if let Ethernet2(value) = self {
16             Some(value)
17         } else {
18             None
19         }
20     }
21 
22     /// Returns `Option::Some` containing the `Ethernet2Header` if self has the
23     /// value Ethernet2. Otherwise `Option::None` is returned.
mut_ethernet2(&mut self) -> Option<&mut Ethernet2Header>24     pub fn mut_ethernet2(&mut self) -> Option<&mut Ethernet2Header> {
25         use crate::LinkHeader::*;
26         if let Ethernet2(value) = self {
27             Some(value)
28         } else {
29             None
30         }
31     }
32 
33     /// Returns `Option::Some` containing the `LinuxSllHeader` if self has the
34     /// value LinuxSll. Otherwise `Option::None` is returned.
linux_sll(self) -> Option<LinuxSllHeader>35     pub fn linux_sll(self) -> Option<LinuxSllHeader> {
36         use crate::LinkHeader::*;
37         if let LinuxSll(value) = self {
38             Some(value)
39         } else {
40             None
41         }
42     }
43 
44     /// Returns `Option::Some` containing the `LinuxSllHeader` if self has the
45     /// value LinuxSll. Otherwise `Option::None` is returned.
mut_linux_sll(&mut self) -> Option<&mut LinuxSllHeader>46     pub fn mut_linux_sll(&mut self) -> Option<&mut LinuxSllHeader> {
47         use crate::LinkHeader::*;
48         if let LinuxSll(value) = self {
49             Some(value)
50         } else {
51             None
52         }
53     }
54 
55     /// Returns the size of the link header
header_len(&self) -> usize56     pub fn header_len(&self) -> usize {
57         use crate::LinkHeader::*;
58         match self {
59             Ethernet2(_) => Ethernet2Header::LEN,
60             LinuxSll(_) => LinuxSllHeader::LEN,
61         }
62     }
63 
64     /// Write the link header to the given writer.
65     #[cfg(feature = "std")]
66     #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error>67     pub fn write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error> {
68         use crate::LinkHeader::*;
69         match self {
70             Ethernet2(value) => value.write(writer),
71             LinuxSll(value) => value.write(writer),
72         }
73     }
74 }
75 
76 #[cfg(test)]
77 mod test {
78     use super::*;
79     use crate::{test_gens::*, *};
80     use alloc::{format, vec::Vec};
81     use proptest::prelude::*;
82     use std::io::Cursor;
83 
84     proptest! {
85         #[test]
86         fn debug(
87             ethernet2 in ethernet_2_any(),
88             linux_sll in linux_sll_any(),
89         ) {
90             assert_eq!(
91                 format!("Ethernet2({:?})", ethernet2),
92                 format!("{:?}", LinkHeader::Ethernet2(ethernet2.clone())),
93             );
94             assert_eq!(
95                 format!("LinuxSll({:?})", linux_sll),
96                 format!("{:?}", LinkHeader::LinuxSll(linux_sll.clone())),
97             );
98         }
99     }
100 
101     proptest! {
102         #[test]
103         fn clone_eq(
104             ethernet2 in ethernet_2_any(),
105             linux_sll in linux_sll_any(),
106         ) {
107             let values = [
108                 LinkHeader::Ethernet2(ethernet2),
109                 LinkHeader::LinuxSll(linux_sll),
110             ];
111             for value in values {
112                 assert_eq!(value.clone(), value);
113             }
114         }
115     }
116 
117     proptest! {
118         #[test]
119         fn ethernet2(
120             ethernet2 in ethernet_2_any(),
121             linux_sll in linux_sll_any()
122         ) {
123             assert_eq!(Some(ethernet2.clone()), LinkHeader::Ethernet2(ethernet2).ethernet2());
124             assert_eq!(None, LinkHeader::LinuxSll(linux_sll).ethernet2());
125         }
126 
127     }
128     proptest! {
129         #[test]
130         fn mut_ethernet2(
131             ethernet2 in ethernet_2_any(),
132             linux_sll in linux_sll_any()
133         ) {
134             assert_eq!(Some(&mut ethernet2.clone()), LinkHeader::Ethernet2(ethernet2).mut_ethernet2());
135             assert_eq!(None, LinkHeader::LinuxSll(linux_sll).mut_ethernet2());
136         }
137     }
138 
139     proptest! {
140         #[test]
141         fn linux_sll(
142             ethernet2 in ethernet_2_any(),
143             linux_sll in linux_sll_any()
144         ) {
145             assert_eq!(Some(linux_sll.clone()), LinkHeader::LinuxSll(linux_sll).linux_sll());
146             assert_eq!(None, LinkHeader::Ethernet2(ethernet2).linux_sll());
147         }
148 
149     }
150     proptest! {
151         #[test]
152         fn mut_linux_sll(
153             ethernet2 in ethernet_2_any(),
154             linux_sll in linux_sll_any()
155         ) {
156             assert_eq!(Some(&mut linux_sll.clone()), LinkHeader::LinuxSll(linux_sll).mut_linux_sll());
157             assert_eq!(None, LinkHeader::Ethernet2(ethernet2).mut_linux_sll());
158         }
159     }
160 
161     proptest! {
162         #[test]
163         fn header_size(
164             ethernet2 in ethernet_2_any(),
165             linux_sll in linux_sll_any()
166         ) {
167             assert_eq!(
168                 LinkHeader::Ethernet2(ethernet2).header_len(),
169                 Ethernet2Header::LEN
170             );
171             assert_eq!(
172                 LinkHeader::LinuxSll(linux_sll.clone()).header_len(),
173                 LinuxSllHeader::LEN
174             );
175         }
176     }
177 
178     proptest! {
179         #[test]
180         fn write(
181             ethernet2 in ethernet_2_any(),
182             linux_sll in linux_sll_any()
183         ) {
184             // ethernet2
185             {
186                 //write
187                 {
188                     let result_input = {
189                         let mut buffer = Vec::new();
190                         ethernet2.write(&mut buffer).unwrap();
191                         buffer
192                     };
193                     let result_transport = {
194                         let mut buffer = Vec::new();
195                         LinkHeader::Ethernet2(ethernet2.clone()).write(&mut buffer).unwrap();
196                         buffer
197                     };
198                     assert_eq!(result_input, result_transport);
199                 }
200                 //trigger an error
201                 {
202                     let mut a: [u8;0] = [];
203                     assert!(
204                         LinkHeader::Ethernet2(ethernet2.clone())
205                         .write(&mut Cursor::new(&mut a[..]))
206                         .is_err()
207                     );
208                 }
209             }
210             // linux_sll
211             {
212                 //write
213                 {
214                     let result_input = {
215                         let mut buffer = Vec::new();
216                         linux_sll.write(&mut buffer).unwrap();
217                         buffer
218                     };
219                     let result_transport = {
220                         let mut buffer = Vec::new();
221                         LinkHeader::LinuxSll(linux_sll.clone()).write(&mut buffer).unwrap();
222                         buffer
223                     };
224                     assert_eq!(result_input, result_transport);
225                 }
226                 //trigger an error
227                 {
228                     let mut a: [u8;0] = [];
229                     assert!(
230                         LinkHeader::LinuxSll(linux_sll.clone())
231                         .write(&mut Cursor::new(&mut a[..]))
232                         .is_err()
233                     );
234                 }
235             }
236         }
237     }
238 }
239