Skip to main content

etherparse/link/
link_header.rs

1use crate::{Ethernet2Header, LinuxSllHeader};
2
3/// The possible headers on the link layer
4#[derive(Clone, Debug, Eq, PartialEq)]
5pub enum LinkHeader {
6    LinuxSll(LinuxSllHeader),
7    Ethernet2(Ethernet2Header),
8}
9
10impl LinkHeader {
11    /// Returns `Option::Some` containing the `Ethernet2Header` if self has the
12    /// value Ethernet2. Otherwise `Option::None` is returned.
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.
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.
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.
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
56    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")))]
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)]
77mod 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}