etherparse/link/
single_vlan_slice.rs1use crate::{err::*, *};
2
3#[derive(Clone, Eq, PartialEq)]
5pub struct SingleVlanSlice<'a> {
6 pub(crate) slice: &'a [u8],
7}
8
9impl<'a> SingleVlanSlice<'a> {
10 pub fn from_slice(slice: &'a [u8]) -> Result<SingleVlanSlice<'a>, LenError> {
13 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 #[inline]
29 pub fn slice(&self) -> &'a [u8] {
30 self.slice
31 }
32
33 #[inline]
38 pub fn priority_code_point(&self) -> VlanPcp {
39 unsafe {
40 VlanPcp::new_unchecked((*self.slice.get_unchecked(0) >> 5) & 0b0000_0111)
43 }
44 }
45
46 #[inline]
51 pub fn drop_eligible_indicator(&self) -> bool {
52 unsafe { 0 != (*self.slice.get_unchecked(0) & 0x10) }
55 }
56
57 #[inline]
59 pub fn vlan_identifier(&self) -> VlanId {
60 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 #[inline]
77 pub fn ether_type(&self) -> EtherType {
78 EtherType(unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(2)) })
81 }
82
83 #[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 pub fn header_slice(&self) -> &[u8] {
96 unsafe {
97 core::slice::from_raw_parts(self.slice.as_ptr(), SingleVlanHeader::LEN)
101 }
102 }
103
104 #[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 #[inline]
117 pub fn payload_slice(&self) -> &'a [u8] {
118 unsafe {
119 core::slice::from_raw_parts(
123 self.slice.as_ptr().add(SingleVlanHeader::LEN),
124 self.slice.len() - SingleVlanHeader::LEN,
125 )
126 }
127 }
128
129 #[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 let slice = SingleVlanSlice::from_slice(&data).unwrap();
168
169 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 {
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 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}