Thanks to visit codestin.com
Credit goes to docs.rs

etherparse/link/
ethernet2_header.rs

1use crate::{err::Layer, err::SliceWriteSpaceError, *};
2
3/// Ethernet II header.
4#[derive(Clone, Debug, Eq, PartialEq, Default)]
5pub struct Ethernet2Header {
6    /// Source MAC Address
7    pub source: [u8; 6],
8    /// Destination MAC Address
9    pub destination: [u8; 6],
10    /// Protocol present after the ethernet2 header.
11    pub ether_type: EtherType,
12}
13
14impl Ethernet2Header {
15    /// Serialized size of an Ethernet2 header in bytes/octets.
16    pub const LEN: usize = 14;
17
18    /// Deprecated use [`Ethernet2Header::LEN`] instead.
19    #[deprecated(since = "0.14.0", note = "Use `Ethernet2Header::LEN` instead")]
20    pub const SERIALIZED_SIZE: usize = Ethernet2Header::LEN;
21
22    /// Deprecated use [`Ethernet2Header::from_slice`] instead.
23    #[deprecated(since = "0.10.1", note = "Use Ethernet2Header::from_slice instead.")]
24    #[inline]
25    pub fn read_from_slice(slice: &[u8]) -> Result<(Ethernet2Header, &[u8]), err::LenError> {
26        Ethernet2Header::from_slice(slice)
27    }
28
29    /// Read an Ethernet2Header from a slice and return the header & unused parts of the slice.
30    #[inline]
31    pub fn from_slice(slice: &[u8]) -> Result<(Ethernet2Header, &[u8]), err::LenError> {
32        Ok((
33            Ethernet2HeaderSlice::from_slice(slice)?.to_header(),
34            &slice[Ethernet2Header::LEN..],
35        ))
36    }
37
38    /// Read an Ethernet2Header from a static sized byte array.
39    #[inline]
40    pub fn from_bytes(bytes: [u8; 14]) -> Ethernet2Header {
41        Ethernet2Header {
42            destination: [bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]],
43            source: [bytes[6], bytes[7], bytes[8], bytes[9], bytes[10], bytes[11]],
44            ether_type: EtherType(u16::from_be_bytes([bytes[12], bytes[13]])),
45        }
46    }
47
48    /// Reads an Ethernet-II header from the current position of the read argument.
49    #[cfg(feature = "std")]
50    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
51    pub fn read<T: std::io::Read + std::io::Seek + Sized>(
52        reader: &mut T,
53    ) -> Result<Ethernet2Header, std::io::Error> {
54        let buffer = {
55            let mut buffer = [0; Ethernet2Header::LEN];
56            reader.read_exact(&mut buffer)?;
57            buffer
58        };
59
60        Ok(
61            // SAFETY: Safe as the buffer contains exactly the needed Ethernet2Header::LEN bytes.
62            unsafe { Ethernet2HeaderSlice::from_slice_unchecked(&buffer) }.to_header(),
63        )
64    }
65
66    /// Serialize the header to a given slice. Returns the unused part of the slice.
67    pub fn write_to_slice<'a>(
68        &self,
69        slice: &'a mut [u8],
70    ) -> Result<&'a mut [u8], SliceWriteSpaceError> {
71        // length check
72        if slice.len() < Ethernet2Header::LEN {
73            Err(SliceWriteSpaceError {
74                required_len: Ethernet2Header::LEN,
75                len: slice.len(),
76                layer: Layer::Ethernet2Header,
77                layer_start_offset: 0,
78            })
79        } else {
80            slice[..Ethernet2Header::LEN].copy_from_slice(&self.to_bytes());
81            Ok(&mut slice[Ethernet2Header::LEN..])
82        }
83    }
84
85    /// Writes a given Ethernet-II header to the current position of the write argument.
86    #[cfg(feature = "std")]
87    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
88    #[inline]
89    pub fn write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error> {
90        writer.write_all(&self.to_bytes())
91    }
92
93    /// Length of the serialized header in bytes.
94    #[inline]
95    pub fn header_len(&self) -> usize {
96        14
97    }
98
99    /// Returns the serialized form of the header as a statically
100    /// sized byte array.
101    #[inline]
102    pub fn to_bytes(&self) -> [u8; 14] {
103        let ether_type_be = self.ether_type.0.to_be_bytes();
104        [
105            self.destination[0],
106            self.destination[1],
107            self.destination[2],
108            self.destination[3],
109            self.destination[4],
110            self.destination[5],
111            self.source[0],
112            self.source[1],
113            self.source[2],
114            self.source[3],
115            self.source[4],
116            self.source[5],
117            ether_type_be[0],
118            ether_type_be[1],
119        ]
120    }
121}
122
123#[cfg(test)]
124mod test {
125    use super::*;
126    use crate::test_gens::*;
127    use alloc::{format, vec::Vec};
128    use proptest::prelude::*;
129    use std::io::{Cursor, ErrorKind};
130
131    #[test]
132    fn default() {
133        let e: Ethernet2Header = Default::default();
134        assert_eq!([0u8; 6], e.source);
135        assert_eq!([0u8; 6], e.destination);
136        assert_eq!(EtherType(0), e.ether_type);
137    }
138
139    proptest! {
140        #[test]
141        fn from_slice(
142            input in ethernet_2_any(),
143            dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
144        ) {
145            // serialize
146            let mut buffer: Vec<u8> = Vec::with_capacity(14 + dummy_data.len());
147            input.write(&mut buffer).unwrap();
148            buffer.extend(&dummy_data[..]);
149
150            // calls with a valid result
151            {
152                let (result, rest) = Ethernet2Header::from_slice(&buffer[..]).unwrap();
153                assert_eq!(input, result);
154                assert_eq!(&buffer[14..], rest);
155            }
156            #[allow(deprecated)]
157            {
158                let (result, rest) = Ethernet2Header::read_from_slice(&buffer[..]).unwrap();
159                assert_eq!(input, result);
160                assert_eq!(&buffer[14..], rest);
161            }
162
163            // call with not enough data in the slice
164            for len in 0..=13 {
165                assert_eq!(
166                    Ethernet2Header::from_slice(&buffer[..len]),
167                    Err(err::LenError{
168                        required_len: Ethernet2Header::LEN,
169                        len: len,
170                        len_source: LenSource::Slice,
171                        layer: err::Layer::Ethernet2Header,
172                        layer_start_offset: 0,
173                    })
174                );
175            }
176        }
177    }
178
179    proptest! {
180        #[test]
181        fn from_bytes(input in ethernet_2_any()) {
182            assert_eq!(
183                input,
184                Ethernet2Header::from_bytes(input.to_bytes())
185            );
186        }
187    }
188
189    proptest! {
190        #[test]
191        fn read(
192            input in ethernet_2_any(),
193            dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
194        ) {
195            // normal read
196            let mut buffer = Vec::with_capacity(14 + dummy_data.len());
197            input.write(&mut buffer).unwrap();
198            buffer.extend(&dummy_data[..]);
199
200            // calls with a valid result
201            {
202                let mut cursor = Cursor::new(&buffer);
203                let result = Ethernet2Header::read(&mut cursor).unwrap();
204                assert_eq!(input, result);
205                assert_eq!(cursor.position(), 14);
206            }
207
208            // unexpected eof
209            for len in 0..=13 {
210                let mut cursor = Cursor::new(&buffer[0..len]);
211                assert_eq!(
212                    Ethernet2Header::read(&mut cursor)
213                    .unwrap_err()
214                    .kind(),
215                    ErrorKind::UnexpectedEof
216                );
217            }
218        }
219    }
220
221    proptest! {
222        #[test]
223        fn write_to_slice(input in ethernet_2_any()) {
224            // normal write
225            {
226                let mut buffer: [u8;14] = [0;14];
227                input.write_to_slice(&mut buffer).unwrap();
228                assert_eq!(buffer, input.to_bytes());
229            }
230            // len to small
231            for len in 0..14 {
232                let mut buffer: [u8;14] = [0;14];
233                assert_eq!(
234                    SliceWriteSpaceError {
235                        required_len: Ethernet2Header::LEN,
236                        len,
237                        layer: Layer::Ethernet2Header,
238                        layer_start_offset: 0,
239                    },
240                    input.write_to_slice(&mut buffer[..len]).unwrap_err()
241                );
242            }
243        }
244    }
245
246    proptest! {
247        #[test]
248        fn write(input in ethernet_2_any()) {
249            // successful write
250            {
251                let mut buffer: Vec<u8> = Vec::with_capacity(14);
252                input.write(&mut buffer).unwrap();
253                assert_eq!(&buffer[..], &input.to_bytes());
254            }
255
256            // not enough memory for write (unexpected eof)
257            for len in 0..8 {
258                let mut buffer = [0u8;8];
259                let mut writer = Cursor::new(&mut buffer[..len]);
260                assert!(input.write(&mut writer).is_err());
261            }
262        }
263    }
264
265    proptest! {
266        #[test]
267        fn header_len(input in ethernet_2_any()) {
268            assert_eq!(input.header_len(), 14);
269        }
270    }
271
272    proptest! {
273        #[test]
274        fn to_bytes(input in ethernet_2_any()) {
275            let ether_type_be = input.ether_type.0.to_be_bytes();
276            assert_eq!(
277                input.to_bytes(),
278                [
279                    input.destination[0],
280                    input.destination[1],
281                    input.destination[2],
282                    input.destination[3],
283                    input.destination[4],
284                    input.destination[5],
285                    input.source[0],
286                    input.source[1],
287                    input.source[2],
288                    input.source[3],
289                    input.source[4],
290                    input.source[5],
291                    ether_type_be[0],
292                    ether_type_be[1],
293                ]
294            );
295        }
296    }
297
298    proptest! {
299        #[test]
300        fn clone_eq(input in ethernet_2_any()) {
301            assert_eq!(input, input.clone());
302        }
303    }
304
305    proptest! {
306        #[test]
307        fn dbg(input in ethernet_2_any()) {
308            assert_eq!(
309                &format!(
310                    "Ethernet2Header {{ source: {:?}, destination: {:?}, ether_type: {:?} }}",
311                    input.source,
312                    input.destination,
313                    input.ether_type
314                ),
315                &format!("{:?}", input)
316            );
317        }
318    }
319}