1use crate::{
2 err::{self, Layer},
3 ArpHardwareId, LenSource, LinuxSllHeader, LinuxSllHeaderSlice, LinuxSllPacketType,
4 LinuxSllPayloadSlice, LinuxSllProtocolType,
5};
6
7#[derive(Clone, Eq, PartialEq)]
9pub struct LinuxSllSlice<'a> {
10 header_slice: LinuxSllHeaderSlice<'a>,
11 header_and_payload_slice: &'a [u8],
12}
13
14impl<'a> LinuxSllSlice<'a> {
15 pub fn from_slice(
18 slice: &'a [u8],
19 ) -> Result<LinuxSllSlice<'a>, err::linux_sll::HeaderSliceError> {
20 if slice.len() < LinuxSllHeader::LEN {
22 return Err(err::linux_sll::HeaderSliceError::Len(err::LenError {
23 required_len: LinuxSllHeader::LEN,
24 len: slice.len(),
25 len_source: LenSource::Slice,
26 layer: Layer::LinuxSllHeader,
27 layer_start_offset: 0,
28 }));
29 }
30
31 match LinuxSllHeaderSlice::from_slice(&slice[0..LinuxSllHeader::LEN]) {
33 Err(err) => Err(err),
34 Ok(header_slice) => Ok(LinuxSllSlice {
35 header_slice,
36 header_and_payload_slice: slice,
37 }),
38 }
39 }
40
41 #[inline]
44 pub fn slice(&self) -> &'a [u8] {
45 self.header_and_payload_slice
46 }
47
48 #[inline]
50 pub fn packet_type(&self) -> LinuxSllPacketType {
51 self.header_slice.packet_type()
52 }
53
54 #[inline]
56 pub fn arp_hardware_type(&self) -> ArpHardwareId {
57 self.header_slice.arp_hardware_type()
58 }
59
60 #[inline]
62 pub fn sender_address_valid_length(&self) -> u16 {
63 self.header_slice.sender_address_valid_length()
64 }
65
66 #[inline]
69 pub fn sender_address_full(&self) -> [u8; 8] {
70 self.header_slice.sender_address_full()
71 }
72
73 #[inline]
76 pub fn sender_address(&self) -> &'a [u8] {
77 self.header_slice.sender_address()
78 }
79
80 #[inline]
82 pub fn protocol_type(&self) -> LinuxSllProtocolType {
83 self.header_slice.protocol_type()
84 }
85
86 pub fn to_header(&self) -> LinuxSllHeader {
89 LinuxSllHeader {
90 packet_type: self.packet_type(),
91 arp_hrd_type: self.arp_hardware_type(),
92 sender_address_valid_length: self.sender_address_valid_length(),
93 sender_address: self.sender_address_full(),
94 protocol_type: self.protocol_type(),
95 }
96 }
97
98 pub fn header_slice(&self) -> &[u8] {
100 self.header_slice.slice()
101 }
102
103 #[inline]
106 pub fn payload(&self) -> LinuxSllPayloadSlice<'a> {
107 LinuxSllPayloadSlice {
108 protocol_type: self.protocol_type(),
109 payload: self.payload_slice(),
110 }
111 }
112
113 #[inline]
115 pub fn payload_slice(&self) -> &'a [u8] {
116 unsafe {
119 core::slice::from_raw_parts(
120 self.header_and_payload_slice
121 .as_ptr()
122 .add(LinuxSllHeader::LEN),
123 self.header_and_payload_slice.len() - LinuxSllHeader::LEN,
124 )
125 }
126 }
127
128 #[inline]
130 pub const fn header_len(&self) -> usize {
131 LinuxSllHeader::LEN
132 }
133}
134
135impl core::fmt::Debug for LinuxSllSlice<'_> {
136 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
137 f.debug_struct("LinuxSllSlice")
138 .field("header", &self.to_header())
139 .field("payload", &self.payload())
140 .finish()
141 }
142}
143
144#[cfg(test)]
145mod test {
146 use super::*;
147 use crate::test_gens::*;
148 use alloc::{format, vec::Vec};
149 use proptest::prelude::*;
150
151 proptest! {
152 #[test]
153 fn debug_clone_eq(
154 linux_sll in linux_sll_any()
155 ) {
156 let payload: [u8;8] = [1,2,3,4,5,6,7,8];
157 let mut data = Vec::with_capacity(
158 linux_sll.header_len() +
159 payload.len()
160 );
161 data.extend_from_slice(&linux_sll.to_bytes());
162 data.extend_from_slice(&payload);
163
164 let slice = LinuxSllSlice::from_slice(&data).unwrap();
166
167 prop_assert_eq!(
169 format!("{:?}", slice),
170 format!(
171 "LinuxSllSlice {{ header: {:?}, payload: {:?} }}",
172 slice.to_header(),
173 slice.payload(),
174 )
175 );
176 prop_assert_eq!(slice.clone(), slice);
177 }
178 }
179
180 proptest! {
181 #[test]
182 fn getters(linux_sll in linux_sll_any()) {
183 let payload: [u8;8] = [1,2,3,4,5,6,7,8];
184 let mut data = Vec::with_capacity(
185 linux_sll.header_len() +
186 payload.len()
187 );
188 data.extend_from_slice(&linux_sll.to_bytes());
189 data.extend_from_slice(&payload);
190
191 let slice = LinuxSllSlice::from_slice(&data).unwrap();
192 assert_eq!(linux_sll.packet_type, slice.packet_type());
193 assert_eq!(linux_sll.arp_hrd_type, slice.arp_hardware_type());
194 assert_eq!(linux_sll.sender_address_valid_length, slice.sender_address_valid_length());
195 assert_eq!(linux_sll.sender_address, slice.sender_address_full());
196 assert_eq!(&linux_sll.sender_address[..usize::from(linux_sll.sender_address_valid_length)], slice.sender_address());
197 assert_eq!(linux_sll.protocol_type, slice.protocol_type());
198 assert_eq!(&payload, slice.payload_slice());
199 assert_eq!(
200 LinuxSllPayloadSlice{
201 payload: &payload,
202 protocol_type: linux_sll.protocol_type,
203 },
204 slice.payload()
205 );
206 assert_eq!(linux_sll, slice.to_header());
207 assert_eq!(&data, slice.slice());
208 assert_eq!(&data[..LinuxSllHeader::LEN], slice.header_slice());
209 }
210 }
211
212 proptest! {
213 #[test]
214 fn from_slice(linux_sll in linux_sll_any()) {
215
216 let payload: [u8;10] = [1,2,3,4,5,6,7,8,9,10];
217 let data = {
218 let mut data = Vec::with_capacity(
219 linux_sll.header_len() +
220 payload.len()
221 );
222 data.extend_from_slice(&linux_sll.to_bytes());
223 data.extend_from_slice(&payload);
224 data
225 };
226
227 {
229 let slice = LinuxSllSlice::from_slice(&data).unwrap();
230 assert_eq!(slice.to_header(), linux_sll);
231 assert_eq!(slice.payload_slice(), &payload);
232 }
233
234 {
236 let slice = LinuxSllSlice::from_slice(&data[..LinuxSllHeader::LEN]).unwrap();
237 assert_eq!(slice.to_header(), linux_sll);
238 assert_eq!(slice.payload_slice(), &[]);
239 }
240
241 for len in 0..LinuxSllHeader::LEN {
243 assert_eq!(
244 LinuxSllSlice::from_slice(&data[..len]).unwrap_err(),
245 err::linux_sll::HeaderSliceError::Len(err::LenError{
246 required_len: LinuxSllHeader::LEN,
247 len,
248 len_source: LenSource::Slice,
249 layer: Layer::LinuxSllHeader,
250 layer_start_offset: 0
251 })
252 );
253 }
254 }
255 }
256}