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

etherparse/link/
single_vlan_slice.rs

1use crate::{err::*, *};
2
3/// Slice containing a VLAN header & payload.
4#[derive(Clone, Eq, PartialEq)]
5pub struct SingleVlanSlice<'a> {
6    pub(crate) slice: &'a [u8],
7}
8
9impl<'a> SingleVlanSlice<'a> {
10    /// Try creating a [`SingleVlanSlice`] from a slice containing the
11    /// VLAN header & payload.
12    pub fn from_slice(slice: &'a [u8]) -> Result<SingleVlanSlice<'a>, LenError> {
13        // check length
14        if slice.len() < SingleVlanHeader::LEN {
15            return Err(err::LenError {
16                required_len: SingleVlanHeader::LEN,
17                len: slice.len(),
18                len_source: LenSource::Slice,
19                layer: err::Layer::VlanHeader,
20                layer_start_offset: 0,
21            });
22        }
23
24        Ok(SingleVlanSlice { slice })
25    }
26
27    /// Returns the slice containing the VLAN header and payload.
28    #[inline]
29    pub fn slice(&self) -> &'a [u8] {
30        self.slice
31    }
32
33    /// Read the "priority_code_point" field of the VLAN header.
34    ///
35    /// This is a 3 bit number which refers to the IEEE 802.1p class
36    /// of service and maps to the frame priority level.
37    #[inline]
38    pub fn priority_code_point(&self) -> VlanPcp {
39        unsafe {
40            // SAFETY: Safe as slice len checked in constructor to be at least 4 &
41            // the bit mask guarantees values does not exceed 0b0000_0111.
42            VlanPcp::new_unchecked((*self.slice.get_unchecked(0) >> 5) & 0b0000_0111)
43        }
44    }
45
46    /// Read the "drop_eligible_indicator" flag of the VLAN header.
47    ///
48    /// Indicates that the frame may be dropped under the presence
49    /// of congestion.
50    #[inline]
51    pub fn drop_eligible_indicator(&self) -> bool {
52        // SAFETY:
53        // Slice len checked in constructor to be at least 4.
54        unsafe { 0 != (*self.slice.get_unchecked(0) & 0x10) }
55    }
56
57    /// Reads the 12 bits "vlan identifier" field from the VLAN header.
58    #[inline]
59    pub fn vlan_identifier(&self) -> VlanId {
60        // SAFETY:
61        // Slice len checked in constructor to be at least 4 &
62        // value and the value is guaranteed not to exceed
63        // 0b0000_1111_1111_1111 as the upper bits have been
64        // bit-masked out.
65        unsafe {
66            VlanId::new_unchecked(u16::from_be_bytes([
67                *self.slice.get_unchecked(0) & 0b0000_1111,
68                *self.slice.get_unchecked(1),
69            ]))
70        }
71    }
72
73    /// Read the "Tag protocol identifier" field from the VLAN header.
74    ///
75    /// Refer to the "EtherType" for a list of possible supported values.
76    #[inline]
77    pub fn ether_type(&self) -> EtherType {
78        // SAFETY:
79        // Slice len checked in constructor to be at least 4.
80        EtherType(unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(2)) })
81    }
82
83    /// Decode all the fields and copy the results to a SingleVlanHeader struct
84    #[inline]
85    pub fn to_header(&self) -> SingleVlanHeader {
86        SingleVlanHeader {
87            pcp: self.priority_code_point(),
88            drop_eligible_indicator: self.drop_eligible_indicator(),
89            vlan_id: self.vlan_identifier(),
90            ether_type: self.ether_type(),
91        }
92    }
93
94    /// Slice containing the Ethernet 2 header.
95    pub fn header_slice(&self) -> &[u8] {
96        unsafe {
97            // SAFETY:
98            // Safe as the constructor checks that the slice has
99            // at least the length of SingleVlanHeader::LEN (4).
100            core::slice::from_raw_parts(self.slice.as_ptr(), SingleVlanHeader::LEN)
101        }
102    }
103
104    /// Returns the slice containing the VLAN payload & ether type
105    /// identifying it's content type.
106    #[inline]
107    pub fn payload(&self) -> EtherPayloadSlice<'a> {
108        EtherPayloadSlice {
109            ether_type: self.ether_type(),
110            len_source: LenSource::Slice,
111            payload: self.payload_slice(),
112        }
113    }
114
115    /// Returns the slice containing the VLAN payload.
116    #[inline]
117    pub fn payload_slice(&self) -> &'a [u8] {
118        unsafe {
119            // SAFETY:
120            // Safe as the constructor checks that the slice has
121            // at least the length of SingleVlanHeader::LEN (4).
122            core::slice::from_raw_parts(
123                self.slice.as_ptr().add(SingleVlanHeader::LEN),
124                self.slice.len() - SingleVlanHeader::LEN,
125            )
126        }
127    }
128
129    /// Length of the VLAN header in bytes (equal to
130    /// [`crate::SingleVlanHeader::LEN`]).
131    #[inline]
132    pub const fn header_len(&self) -> usize {
133        SingleVlanHeader::LEN
134    }
135}
136
137impl core::fmt::Debug for SingleVlanSlice<'_> {
138    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
139        f.debug_struct("SingleVlanSlice")
140            .field("header", &self.to_header())
141            .field("payload", &self.payload())
142            .finish()
143    }
144}
145
146#[cfg(test)]
147mod test {
148    use super::*;
149    use crate::test_gens::*;
150    use alloc::{format, vec::Vec};
151    use proptest::prelude::*;
152
153    proptest! {
154        #[test]
155        fn debug_clone_eq(
156            vlan in vlan_single_any()
157        ) {
158            let payload: [u8;8] = [1,2,3,4,5,6,7,8];
159            let mut data = Vec::with_capacity(
160                vlan.header_len() +
161                payload.len()
162            );
163            data.extend_from_slice(&vlan.to_bytes());
164            data.extend_from_slice(&payload);
165
166            // decode packet
167            let slice = SingleVlanSlice::from_slice(&data).unwrap();
168
169            // check debug output
170            prop_assert_eq!(
171                format!("{:?}", slice),
172                format!(
173                    "SingleVlanSlice {{ header: {:?}, payload: {:?} }}",
174                    slice.to_header(),
175                    slice.payload(),
176                )
177            );
178            prop_assert_eq!(slice.clone(), slice);
179        }
180    }
181
182    proptest! {
183        #[test]
184        fn getters(vlan in vlan_single_any()) {
185            let payload: [u8;8] = [1,2,3,4,5,6,7,8];
186            let mut data = Vec::with_capacity(
187                vlan.header_len() +
188                payload.len()
189            );
190            data.extend_from_slice(&vlan.to_bytes());
191            data.extend_from_slice(&payload);
192
193            let slice = SingleVlanSlice::from_slice(&data).unwrap();
194            assert_eq!(&data, slice.slice());
195            assert_eq!(vlan.pcp, slice.priority_code_point());
196            assert_eq!(vlan.drop_eligible_indicator, slice.drop_eligible_indicator());
197            assert_eq!(vlan.vlan_id, slice.vlan_identifier());
198            assert_eq!(vlan.ether_type, slice.ether_type());
199            assert_eq!(vlan, slice.to_header());
200            assert_eq!(&data[..SingleVlanHeader::LEN], slice.header_slice());
201
202            assert_eq!(
203                EtherPayloadSlice {
204                    ether_type: vlan.ether_type,
205                    len_source: LenSource::Slice,
206                    payload: &data[SingleVlanHeader::LEN..],
207                },
208                slice.payload()
209            );
210            assert_eq!(&data[SingleVlanHeader::LEN..], slice.payload_slice());
211            assert_eq!(SingleVlanHeader::LEN, slice.header_len());
212        }
213    }
214
215    proptest! {
216        #[test]
217        fn from_slice(vlan in vlan_single_any()) {
218
219            let payload: [u8;10] = [1,2,3,4,5,6,7,8,9,10];
220            let data = {
221                let mut data = Vec::with_capacity(
222                    vlan.header_len() +
223                    payload.len()
224                );
225                data.extend_from_slice(&vlan.to_bytes());
226                data.extend_from_slice(&payload);
227                data
228            };
229
230            // normal decode
231            {
232                let slice = SingleVlanSlice::from_slice(&data).unwrap();
233                assert_eq!(slice.to_header(), vlan);
234                assert_eq!(slice.payload_slice(), &payload);
235            }
236
237            // length error
238            for len in 0..SingleVlanHeader::LEN {
239                assert_eq!(
240                    SingleVlanSlice::from_slice(&data[..len]).unwrap_err(),
241                    LenError{
242                        required_len: SingleVlanHeader::LEN,
243                        len,
244                        len_source: LenSource::Slice,
245                        layer: Layer::VlanHeader,
246                        layer_start_offset: 0
247                    }
248                );
249            }
250        }
251    }
252}