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

etherparse/link/
single_vlan_header.rs

1use crate::*;
2
3/// IEEE 802.1Q VLAN Tagging Header
4#[derive(Clone, Debug, Eq, PartialEq, Default)]
5pub struct SingleVlanHeader {
6    /// A 3 bit number which refers to the IEEE 802.1p class of service and maps to the frame priority level.
7    pub pcp: VlanPcp,
8    /// Indicate that the frame may be dropped under the presence of congestion.
9    pub drop_eligible_indicator: bool,
10    /// 12 bits vland identifier.
11    pub vlan_id: VlanId,
12    /// "Tag protocol identifier": Type id of content after this header. Refer to the "EtherType" for a list of possible supported values.
13    pub ether_type: EtherType,
14}
15
16impl SingleVlanHeader {
17    /// Serialized size of an VLAN header in bytes/octets.
18    pub const LEN: usize = 4;
19
20    #[deprecated(since = "0.14.0", note = "Use `SingleVlanHeader::LEN` instead")]
21    pub const SERIALIZED_SIZE: usize = SingleVlanHeader::LEN;
22
23    /// Read an SingleVlanHeader from a slice and return the header & unused parts of the slice.
24    #[deprecated(since = "0.10.1", note = "Use SingleVlanHeader::from_slice instead.")]
25    #[inline]
26    pub fn read_from_slice(slice: &[u8]) -> Result<(SingleVlanHeader, &[u8]), err::LenError> {
27        SingleVlanHeader::from_slice(slice)
28    }
29
30    /// Read an SingleVlanHeader from a slice and return the header & unused parts of the slice.
31    #[inline]
32    pub fn from_slice(slice: &[u8]) -> Result<(SingleVlanHeader, &[u8]), err::LenError> {
33        Ok((
34            SingleVlanHeaderSlice::from_slice(slice)?.to_header(),
35            &slice[SingleVlanHeader::LEN..],
36        ))
37    }
38
39    /// Read an SingleVlanHeader from a static sized byte array.
40    #[inline]
41    pub fn from_bytes(bytes: [u8; 4]) -> SingleVlanHeader {
42        SingleVlanHeader {
43            pcp: unsafe {
44                // SAFETY: Safe as bitmasks guarantee that value does not exceed
45                //         0b0000_0111.
46                VlanPcp::new_unchecked((bytes[0] >> 5) & 0b0000_0111u8)
47            },
48            drop_eligible_indicator: 0 != (bytes[0] & 0b0001_0000u8),
49            vlan_id: unsafe {
50                // SAFETY: Safe as bitmasks guarantee that value does not exceed
51                //         0b0000_1111_1111_1111.
52                VlanId::new_unchecked(u16::from_be_bytes([bytes[0] & 0b0000_1111u8, bytes[1]]))
53            },
54            ether_type: EtherType(u16::from_be_bytes([bytes[2], bytes[3]])),
55        }
56    }
57
58    /// Read a IEEE 802.1Q VLAN tagging header
59    #[cfg(feature = "std")]
60    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
61    pub fn read<T: std::io::Read + std::io::Seek + Sized>(
62        reader: &mut T,
63    ) -> Result<SingleVlanHeader, std::io::Error> {
64        let buffer = {
65            let mut buffer: [u8; SingleVlanHeader::LEN] = [0; SingleVlanHeader::LEN];
66            reader.read_exact(&mut buffer)?;
67            buffer
68        };
69
70        Ok(
71            // SAFETY: Safe as the buffer has the exact size of an vlan header.
72            unsafe { SingleVlanHeaderSlice::from_slice_unchecked(&buffer) }.to_header(),
73        )
74    }
75
76    /// Write the IEEE 802.1Q VLAN tagging header
77    #[inline]
78    #[cfg(feature = "std")]
79    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
80    pub fn write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error> {
81        writer.write_all(&self.to_bytes())
82    }
83
84    /// Length of the serialized header in bytes.
85    #[inline]
86    pub fn header_len(&self) -> usize {
87        4
88    }
89
90    /// Returns the serialized form of the header or an value error in case
91    /// the header values are outside of range.
92    #[inline]
93    pub fn to_bytes(&self) -> [u8; 4] {
94        let id_be = self.vlan_id.value().to_be_bytes();
95        let eth_type_be = self.ether_type.0.to_be_bytes();
96        [
97            (if self.drop_eligible_indicator {
98                id_be[0] | 0x10
99            } else {
100                id_be[0]
101            } | (self.pcp.value() << 5)),
102            id_be[1],
103            eth_type_be[0],
104            eth_type_be[1],
105        ]
106    }
107}
108
109#[cfg(test)]
110mod test {
111    use crate::{test_gens::*, *};
112    use alloc::{format, vec::Vec};
113    use proptest::prelude::*;
114    use std::io::{Cursor, ErrorKind};
115
116    #[test]
117    fn constants() {
118        assert_eq!(4, SingleVlanHeader::LEN);
119    }
120
121    proptest! {
122        #[test]
123        fn from_slice(
124            input in vlan_single_any(),
125            dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
126        ) {
127            // serialize
128            let mut buffer: Vec<u8> = Vec::with_capacity(input.header_len() + dummy_data.len());
129            input.write(&mut buffer).unwrap();
130            buffer.extend(&dummy_data[..]);
131
132            // normal
133            {
134                let (result, rest) = SingleVlanHeader::from_slice(&buffer).unwrap();
135                assert_eq!(result, input);
136                assert_eq!(rest, &buffer[4..]);
137            }
138            #[allow(deprecated)]
139            {
140                let (result, rest) = SingleVlanHeader::read_from_slice(&buffer).unwrap();
141                assert_eq!(result, input);
142                assert_eq!(rest, &buffer[4..]);
143            }
144
145            // slice length to small
146            for len in 0..4 {
147                assert_eq!(
148                    SingleVlanHeader::from_slice(&buffer[..len])
149                        .unwrap_err(),
150                    err::LenError{
151                        required_len: 4,
152                        len: len,
153                        len_source: LenSource::Slice,
154                        layer:  err::Layer::VlanHeader,
155                        layer_start_offset: 0,
156                    }
157                );
158            }
159        }
160    }
161
162    proptest! {
163        #[test]
164        fn from_bytes(input in vlan_single_any()) {
165            let actual = SingleVlanHeader::from_bytes(
166                input.to_bytes()
167            );
168            assert_eq!(actual, input);
169        }
170    }
171
172    proptest! {
173        #[test]
174        fn read(
175            input in vlan_single_any(),
176            dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
177        ) {
178            // serialize
179            let mut buffer: Vec<u8> = Vec::with_capacity(input.header_len() + dummy_data.len());
180            input.write(&mut buffer).unwrap();
181            buffer.extend(&dummy_data[..]);
182
183            // normal
184            {
185                let mut cursor = Cursor::new(&buffer);
186                let result = SingleVlanHeader::read(&mut cursor).unwrap();
187                assert_eq!(result, input);
188                assert_eq!(4, cursor.position());
189            }
190
191            // unexpexted eof
192            for len in 0..4 {
193                let mut cursor = Cursor::new(&buffer[0..len]);
194                assert_eq!(
195                    SingleVlanHeader::read(&mut cursor)
196                    .unwrap_err()
197                    .kind(),
198                    ErrorKind::UnexpectedEof
199                );
200            }
201        }
202    }
203
204    proptest! {
205        #[test]
206        fn write_and_to_bytes(input in vlan_single_any()) {
207            // normal write
208            {
209                let mut buffer: Vec<u8> = Vec::with_capacity(input.header_len());
210                input.write(&mut buffer).unwrap();
211                assert_eq!(&buffer[..], &input.to_bytes());
212                {
213                    let id_be = input.vlan_id.value().to_be_bytes();
214                    let eth_type_be = input.ether_type.0.to_be_bytes();
215                    assert_eq!(
216                        input.to_bytes(),
217                        [
218                            (
219                                id_be[0] | if input.drop_eligible_indicator {
220                                    0x10
221                                } else {
222                                    0
223                                } | (input.pcp.value() << 5)
224                            ),
225                            id_be[1],
226                            eth_type_be[0],
227                            eth_type_be[1]
228                        ]
229                    );
230                }
231            }
232
233            // unexpected eof
234            for len in 0..4 {
235                let mut buffer = [0u8;4];
236                let mut cursor = Cursor::new(&mut buffer[..len]);
237                assert!(input.write(&mut cursor).is_err());
238            }
239        }
240    }
241
242    proptest! {
243        #[test]
244        fn header_len(input in vlan_single_any()) {
245            assert_eq!(4, input.header_len());
246        }
247    }
248
249    #[test]
250    fn default() {
251        let actual: SingleVlanHeader = Default::default();
252        assert_eq!(0, actual.pcp.value());
253        assert_eq!(false, actual.drop_eligible_indicator);
254        assert_eq!(0, actual.vlan_id.value());
255        assert_eq!(0, actual.ether_type.0);
256    }
257
258    proptest! {
259        #[test]
260        fn clone_eq(input in vlan_single_any()) {
261            assert_eq!(input, input.clone());
262        }
263    }
264
265    proptest! {
266        #[test]
267        fn dbg(input in vlan_single_any()) {
268            assert_eq!(
269                &format!(
270                    "SingleVlanHeader {{ pcp: {:?}, drop_eligible_indicator: {}, vlan_id: {:?}, ether_type: {:?} }}",
271                    input.pcp,
272                    input.drop_eligible_indicator,
273                    input.vlan_id,
274                    input.ether_type,
275                ),
276                &format!("{:?}", input)
277            );
278        }
279    }
280}