etherparse/link/
single_vlan_header_slice.rs1use crate::*;
2use core::slice::from_raw_parts;
3
4#[derive(Clone, Debug, Eq, PartialEq)]
6pub struct SingleVlanHeaderSlice<'a> {
7 slice: &'a [u8],
8}
9
10impl<'a> SingleVlanHeaderSlice<'a> {
11 #[inline]
13 pub fn from_slice(slice: &'a [u8]) -> Result<SingleVlanHeaderSlice<'a>, err::LenError> {
14 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 Ok(SingleVlanHeaderSlice::<'a> {
27 slice: unsafe { from_raw_parts(slice.as_ptr(), SingleVlanHeader::LEN) },
31 })
32 }
33
34 #[inline]
46 pub(crate) unsafe fn from_slice_unchecked(slice: &[u8]) -> SingleVlanHeaderSlice {
47 SingleVlanHeaderSlice { slice }
48 }
49
50 #[inline]
52 pub fn slice(&self) -> &'a [u8] {
53 self.slice
54 }
55
56 #[inline]
58 pub fn priority_code_point(&self) -> VlanPcp {
59 unsafe {
60 VlanPcp::new_unchecked((*self.slice.get_unchecked(0) >> 5) & 0b0000_0111)
63 }
64 }
65
66 #[inline]
68 pub fn drop_eligible_indicator(&self) -> bool {
69 unsafe { 0 != (*self.slice.get_unchecked(0) & 0x10) }
72 }
73
74 #[inline]
76 pub fn vlan_identifier(&self) -> VlanId {
77 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 #[inline]
92 pub fn ether_type(&self) -> EtherType {
93 EtherType(unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(2)) })
96 }
97
98 #[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 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 {
129 let slice = SingleVlanHeaderSlice::from_slice(&buffer).unwrap();
130 assert_eq!(slice.slice(), &buffer[..4]);
131 }
132
133 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}