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

etherparse/link/
single_vlan_header_slice.rs

1use crate::*;
2use core::slice::from_raw_parts;
3
4///A slice containing a single vlan header of a network package.
5#[derive(Clone, Debug, Eq, PartialEq)]
6pub struct SingleVlanHeaderSlice<'a> {
7    slice: &'a [u8],
8}
9
10impl<'a> SingleVlanHeaderSlice<'a> {
11    ///Creates a vlan header slice from a slice.
12    #[inline]
13    pub fn from_slice(slice: &'a [u8]) -> Result<SingleVlanHeaderSlice<'a>, err::LenError> {
14        //check length
15        if slice.len() < SingleVlanHeader::LEN {
16            return Err(err::LenError {
17                required_len: SingleVlanHeader::LEN,
18                len: slice.len(),
19                len_source: LenSource::Slice,
20                layer: err::Layer::VlanHeader,
21                layer_start_offset: 0,
22            });
23        }
24
25        //all done
26        Ok(SingleVlanHeaderSlice::<'a> {
27            // SAFETY:
28            // Safe as the slice length is checked beforehand to have
29            // at least the length of SingleVlanHeader::LEN (4)
30            slice: unsafe { from_raw_parts(slice.as_ptr(), SingleVlanHeader::LEN) },
31        })
32    }
33
34    /// Converts the given slice into a vlan header slice WITHOUT any
35    /// checks to ensure that the data present is an vlan header or that the
36    /// slice length is matching the header length.
37    ///
38    /// If you are not sure what this means, use [`SingleVlanHeaderSlice::from_slice`]
39    /// instead.
40    ///
41    /// # Safety
42    ///
43    /// The caller must ensured that the given slice has the length of
44    /// [`SingleVlanHeader::LEN`]
45    #[inline]
46    pub(crate) unsafe fn from_slice_unchecked(slice: &[u8]) -> SingleVlanHeaderSlice {
47        SingleVlanHeaderSlice { slice }
48    }
49
50    /// Returns the slice containing the single vlan header
51    #[inline]
52    pub fn slice(&self) -> &'a [u8] {
53        self.slice
54    }
55
56    /// Read the "priority_code_point" field from the slice. This is a 3 bit number which refers to the IEEE 802.1p class of service and maps to the frame priority level.
57    #[inline]
58    pub fn priority_code_point(&self) -> VlanPcp {
59        unsafe {
60            // SAFETY: Safe as slice len checked in constructor to be at least 4 &
61            // the bitmask guarantees values does not exceed 0b0000_0111.
62            VlanPcp::new_unchecked((*self.slice.get_unchecked(0) >> 5) & 0b0000_0111)
63        }
64    }
65
66    /// Read the "drop_eligible_indicator" flag from the slice. Indicates that the frame may be dropped under the presence of congestion.
67    #[inline]
68    pub fn drop_eligible_indicator(&self) -> bool {
69        // SAFETY:
70        // Slice len checked in constructor to be at least 4.
71        unsafe { 0 != (*self.slice.get_unchecked(0) & 0x10) }
72    }
73
74    /// Reads the 12 bits "vland identifier" field from the slice.
75    #[inline]
76    pub fn vlan_identifier(&self) -> VlanId {
77        // SAFETY:
78        // Slice len checked in constructor to be at least 4 &
79        // value and the value is guaranteed not to exceed
80        // 0b0000_1111_1111_1111 as the upper bits have been
81        // bitmasked out.
82        unsafe {
83            VlanId::new_unchecked(u16::from_be_bytes([
84                *self.slice.get_unchecked(0) & 0b0000_1111,
85                *self.slice.get_unchecked(1),
86            ]))
87        }
88    }
89
90    /// Read the "Tag protocol identifier" field from the slice. Refer to the "EtherType" for a list of possible supported values.
91    #[inline]
92    pub fn ether_type(&self) -> EtherType {
93        // SAFETY:
94        // Slice len checked in constructor to be at least 4.
95        EtherType(unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(2)) })
96    }
97
98    /// Decode all the fields and copy the results to a SingleVlanHeader struct
99    #[inline]
100    pub fn to_header(&self) -> SingleVlanHeader {
101        SingleVlanHeader {
102            pcp: self.priority_code_point(),
103            drop_eligible_indicator: self.drop_eligible_indicator(),
104            vlan_id: self.vlan_identifier(),
105            ether_type: self.ether_type(),
106        }
107    }
108}
109
110#[cfg(test)]
111mod test {
112    use crate::{test_gens::*, *};
113    use alloc::{format, vec::Vec};
114    use proptest::prelude::*;
115
116    proptest! {
117        #[test]
118        fn from_slice(
119            input in vlan_single_any(),
120            dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
121        ) {
122            // serialize
123            let mut buffer: Vec<u8> = Vec::with_capacity(input.header_len() + dummy_data.len());
124            input.write(&mut buffer).unwrap();
125            buffer.extend(&dummy_data[..]);
126
127            // normal
128            {
129                let slice = SingleVlanHeaderSlice::from_slice(&buffer).unwrap();
130                assert_eq!(slice.slice(), &buffer[..4]);
131            }
132
133            // slice length to small
134            for len in 0..4 {
135                assert_eq!(
136                    SingleVlanHeaderSlice::from_slice(&buffer[..len])
137                        .unwrap_err(),
138                    err::LenError{
139                        required_len: 4,
140                        len: len,
141                        len_source: LenSource::Slice,
142                        layer:  err::Layer::VlanHeader,
143                        layer_start_offset: 0,
144                    }
145                );
146            }
147        }
148    }
149
150    proptest! {
151        #[test]
152        fn getters(input in vlan_single_any()) {
153            let bytes = input.to_bytes();
154            let slice = SingleVlanHeaderSlice::from_slice(&bytes).unwrap();
155
156            assert_eq!(input.pcp, slice.priority_code_point());
157            assert_eq!(input.drop_eligible_indicator, slice.drop_eligible_indicator());
158            assert_eq!(input.vlan_id, slice.vlan_identifier());
159            assert_eq!(input.ether_type, slice.ether_type());
160        }
161    }
162
163    proptest! {
164        #[test]
165        fn to_header(input in vlan_single_any()) {
166            let bytes = input.to_bytes();
167            let slice = SingleVlanHeaderSlice::from_slice(&bytes).unwrap();
168            assert_eq!(input, slice.to_header());
169        }
170    }
171
172    proptest! {
173        #[test]
174        fn clone_eq(input in vlan_single_any()) {
175            let bytes = input.to_bytes();
176            let slice = SingleVlanHeaderSlice::from_slice(&bytes).unwrap();
177            assert_eq!(slice, slice.clone());
178        }
179    }
180
181    proptest! {
182        #[test]
183        fn dbg(input in vlan_single_any()) {
184            let bytes = input.to_bytes();
185            let slice = SingleVlanHeaderSlice::from_slice(&bytes).unwrap();
186            assert_eq!(
187                &format!(
188                    "SingleVlanHeaderSlice {{ slice: {:?} }}",
189                    slice.slice(),
190                ),
191                &format!("{:?}", slice)
192            );
193        }
194    }
195}