1use crate::{err::*, *};
2
3#[derive(Clone, Debug, Eq, PartialEq)]
5pub struct UdpSlice<'a> {
6 slice: &'a [u8],
7}
8
9impl<'a> UdpSlice<'a> {
10 pub fn from_slice(slice: &'a [u8]) -> Result<UdpSlice<'a>, LenError> {
16 let header = UdpHeaderSlice::from_slice(slice)?;
18
19 let len: usize = header.length().into();
21 if slice.len() < len {
22 return Err(LenError {
23 required_len: len,
24 len: slice.len(),
25 len_source: LenSource::Slice,
26 layer: Layer::UdpPayload,
27 layer_start_offset: 0,
28 });
29 }
30
31 if len == 0 {
33 Ok(UdpSlice { slice })
34 } else {
35 if len < UdpHeader::LEN {
37 Err(LenError {
39 required_len: UdpHeader::LEN,
40 len,
41 len_source: LenSource::UdpHeaderLen,
42 layer: Layer::UdpHeader,
43 layer_start_offset: 0,
44 })
45 } else {
46 Ok(UdpSlice {
47 slice: unsafe { core::slice::from_raw_parts(slice.as_ptr(), len) },
50 })
51 }
52 }
53 }
54
55 pub fn from_slice_lax(slice: &'a [u8]) -> Result<UdpSlice<'a>, LenError> {
63 let header = UdpHeaderSlice::from_slice(slice)?;
65
66 let len: usize = header.length().into();
69 if slice.len() < len || len < UdpHeader::LEN {
70 Ok(UdpSlice { slice })
71 } else {
72 Ok(UdpSlice {
73 slice: unsafe { core::slice::from_raw_parts(slice.as_ptr(), len) },
76 })
77 }
78 }
79
80 #[inline]
82 pub fn slice(&self) -> &'a [u8] {
83 self.slice
84 }
85
86 #[inline]
88 pub fn header_slice(&self) -> &'a [u8] {
89 unsafe {
90 core::slice::from_raw_parts(self.slice.as_ptr(), UdpHeader::LEN)
93 }
94 }
95
96 #[inline]
98 pub fn payload(&self) -> &'a [u8] {
99 unsafe {
100 core::slice::from_raw_parts(
103 self.slice.as_ptr().add(UdpHeader::LEN),
104 self.slice.len() - UdpHeader::LEN,
105 )
106 }
107 }
108
109 #[inline]
111 pub fn payload_len_source(&self) -> LenSource {
112 if usize::from(self.length()) == self.slice.len() {
113 LenSource::UdpHeaderLen
114 } else {
115 LenSource::Slice
116 }
117 }
118
119 #[inline]
121 pub fn source_port(&self) -> u16 {
122 unsafe { get_unchecked_be_u16(self.slice.as_ptr()) }
126 }
127
128 #[inline]
130 pub fn destination_port(&self) -> u16 {
131 unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(2)) }
135 }
136
137 #[inline]
139 pub fn length(&self) -> u16 {
140 unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(4)) }
144 }
145
146 #[inline]
148 pub fn checksum(&self) -> u16 {
149 unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(6)) }
153 }
154
155 #[inline]
157 pub const fn header_len(&self) -> usize {
158 UdpHeader::LEN
159 }
160
161 #[inline]
163 pub const fn header_len_u16(&self) -> u16 {
164 UdpHeader::LEN_U16
165 }
166
167 #[inline]
170 pub fn to_header(&self) -> UdpHeader {
171 UdpHeader {
172 source_port: self.source_port(),
173 destination_port: self.destination_port(),
174 length: self.length(),
175 checksum: self.checksum(),
176 }
177 }
178}
179
180#[cfg(test)]
181mod test {
182 use super::*;
183 use crate::test_gens::*;
184 use alloc::{format, vec::Vec};
185 use proptest::prelude::*;
186
187 proptest! {
188 #[test]
189 fn debug_clone_eq(
190 udp_base in udp_any()
191 ) {
192 let payload: [u8;4] = [1,2,3,4];
193 let mut data = Vec::with_capacity(
194 udp_base.header_len() +
195 payload.len()
196 );
197 let mut udp = udp_base.clone();
198 udp.length = (UdpHeader::LEN + payload.len()) as u16;
199 data.extend_from_slice(&udp.to_bytes());
200 data.extend_from_slice(&payload);
201
202 let slice = UdpSlice::from_slice(&data).unwrap();
204
205 prop_assert_eq!(
207 format!("{:?}", slice),
208 format!(
209 "UdpSlice {{ slice: {:?} }}",
210 &data[..]
211 )
212 );
213 prop_assert_eq!(slice.clone(), slice);
214 }
215 }
216
217 proptest! {
218 #[test]
219 fn getters(
220 udp_base in udp_any()
221 ) {
222 let udp = {
223 let mut udp = udp_base.clone();
224 udp.length = UdpHeader::LEN as u16;
225 udp
226 };
227 let data = {
228 let mut data = Vec::with_capacity(
229 udp.header_len()
230 );
231 data.extend_from_slice(&udp.to_bytes());
232 data
233 };
234
235 {
237 let slice = UdpSlice::from_slice(&data).unwrap();
238 assert_eq!(slice.slice(), &data);
239 assert_eq!(slice.header_slice(), &data);
240 assert_eq!(slice.payload(), &[]);
241 assert_eq!(slice.source_port(), udp.source_port);
242 assert_eq!(slice.destination_port(), udp.destination_port);
243 assert_eq!(slice.length(), udp.length);
244 assert_eq!(slice.checksum(), udp.checksum);
245 assert_eq!(slice.to_header(), udp);
246 }
247 }
248 }
249
250 proptest! {
251 #[test]
252 fn from_slice(
253 udp_base in udp_any()
254 ) {
255 let payload: [u8;4] = [1,2,3,4];
256 let udp = {
257 let mut udp = udp_base.clone();
258 udp.length = (UdpHeader::LEN + payload.len()) as u16;
259 udp
260 };
261 let data = {
262 let mut data = Vec::with_capacity(
263 udp.header_len() +
264 payload.len()
265 );
266 data.extend_from_slice(&udp.to_bytes());
267 data.extend_from_slice(&payload);
268 data
269 };
270
271 {
273 let slice = UdpSlice::from_slice(&data).unwrap();
274 assert_eq!(udp, slice.to_header());
275 assert_eq!(payload, slice.payload());
276 }
277
278 {
280 let mut mod_data = data.clone();
281 let reduced_len = (UdpHeader::LEN + payload.len() - 1) as u16;
282 {
284 let rl_be = reduced_len.to_be_bytes();
285 mod_data[4] = rl_be[0];
286 mod_data[5] = rl_be[1];
287 }
288
289 let slice = UdpSlice::from_slice(&mod_data).unwrap();
290 assert_eq!(
291 slice.to_header(),
292 {
293 let mut expected = slice.to_header();
294 expected.length = reduced_len;
295 expected
296 }
297 );
298 assert_eq!(&payload[..payload.len() - 1], slice.payload());
299 }
300
301 {
303 let mut mod_data = data.clone();
305 mod_data[4] = 0;
306 mod_data[5] = 0;
307
308 let slice = UdpSlice::from_slice(&mod_data).unwrap();
309
310 assert_eq!(slice.source_port(), udp_base.source_port);
311 assert_eq!(slice.destination_port(), udp_base.destination_port);
312 assert_eq!(slice.checksum(), udp_base.checksum);
313 assert_eq!(slice.length(), 0);
314 assert_eq!(&payload, slice.payload());
315 }
316
317 for len in 0..UdpHeader::LEN {
319 assert_eq!(
320 UdpSlice::from_slice(&data[..len]).unwrap_err(),
321 LenError {
322 required_len: UdpHeader::LEN,
323 len,
324 len_source: LenSource::Slice,
325 layer: Layer::UdpHeader,
326 layer_start_offset: 0,
327 }
328 );
329 }
330
331 assert_eq!(
333 UdpSlice::from_slice(&data[..data.len() - 1]).unwrap_err(),
334 LenError {
335 required_len: data.len(),
336 len: data.len() - 1,
337 len_source: LenSource::Slice,
338 layer: Layer::UdpPayload,
339 layer_start_offset: 0,
340 }
341 );
342
343 {
345 let mut mod_data = data.clone();
346 {
348 let len_be = ((UdpHeader::LEN - 1) as u16).to_be_bytes();
349 mod_data[4] = len_be[0];
350 mod_data[5] = len_be[1];
351 }
352 assert_eq!(
353 UdpSlice::from_slice(&mod_data).unwrap_err(),
354 LenError {
355 required_len: UdpHeader::LEN,
356 len: UdpHeader::LEN - 1,
357 len_source: LenSource::UdpHeaderLen,
358 layer: Layer::UdpHeader,
359 layer_start_offset: 0
360 }
361 );
362 }
363 }
364 }
365
366 proptest! {
367 #[test]
368 fn from_slice_lax(
369 udp_base in udp_any()
370 ) {
371 let payload: [u8;4] = [1,2,3,4];
372 let udp = {
373 let mut udp = udp_base.clone();
374 udp.length = (UdpHeader::LEN + payload.len()) as u16;
375 udp
376 };
377 let data = {
378 let mut data = Vec::with_capacity(
379 udp.header_len() +
380 payload.len()
381 );
382 data.extend_from_slice(&udp.to_bytes());
383 data.extend_from_slice(&payload);
384 data
385 };
386
387 {
389 let slice = UdpSlice::from_slice_lax(&data).unwrap();
390 assert_eq!(udp, slice.to_header());
391 assert_eq!(payload, slice.payload());
392 assert_eq!(slice.payload_len_source(), LenSource::UdpHeaderLen);
393 }
394
395 {
397 let mut mod_data = data.clone();
398 let reduced_len = (UdpHeader::LEN + payload.len() - 1) as u16;
399 {
401 let rl_be = reduced_len.to_be_bytes();
402 mod_data[4] = rl_be[0];
403 mod_data[5] = rl_be[1];
404 }
405
406 let slice = UdpSlice::from_slice_lax(&mod_data).unwrap();
407 assert_eq!(
408 slice.to_header(),
409 {
410 let mut expected = slice.to_header();
411 expected.length = reduced_len;
412 expected
413 }
414 );
415 assert_eq!(&payload[..payload.len() - 1], slice.payload());
416 assert_eq!(slice.payload_len_source(), LenSource::UdpHeaderLen);
417 }
418
419 for len in 0..UdpHeader::LEN_U16{
421 let mut mod_data = data.clone();
423 mod_data[4] = len.to_be_bytes()[0];
424 mod_data[5] = len.to_be_bytes()[1];
425
426 let slice = UdpSlice::from_slice_lax(&mod_data).unwrap();
427
428 assert_eq!(slice.source_port(), udp_base.source_port);
429 assert_eq!(slice.destination_port(), udp_base.destination_port);
430 assert_eq!(slice.checksum(), udp_base.checksum);
431 assert_eq!(slice.length(), len);
432 assert_eq!(&payload, slice.payload());
433 assert_eq!(slice.payload_len_source(), LenSource::Slice);
434 }
435
436 for len in 0..UdpHeader::LEN {
438 assert_eq!(
439 UdpSlice::from_slice_lax(&data[..len]).unwrap_err(),
440 LenError {
441 required_len: UdpHeader::LEN,
442 len,
443 len_source: LenSource::Slice,
444 layer: Layer::UdpHeader,
445 layer_start_offset: 0,
446 }
447 );
448 }
449
450 {
452 let slice = UdpSlice::from_slice_lax(&data[..data.len() - 1]).unwrap();
453 assert_eq!(udp, slice.to_header());
454 assert_eq!(&payload[..payload.len() - 1], slice.payload());
455 assert_eq!(slice.payload_len_source(), LenSource::Slice);
456 }
457 }
458 }
459
460 proptest! {
461 #[test]
462 fn header_len(
463 udp in udp_any()
464 ) {
465 let mut udp = udp.clone();
466 udp.length = UdpHeader::LEN_U16;
467 let bytes = udp.to_bytes();
468 let slice = UdpSlice::from_slice(&bytes).unwrap();
469 assert_eq!(UdpHeader::LEN, slice.header_len());
470 }
471 }
472
473 proptest! {
474 #[test]
475 fn header_len_u16(
476 udp in udp_any()
477 ) {
478 let mut udp = udp.clone();
479 udp.length = UdpHeader::LEN_U16;
480 let bytes = udp.to_bytes();
481 let slice = UdpSlice::from_slice(&bytes).unwrap();
482 assert_eq!(UdpHeader::LEN_U16, slice.header_len_u16());
483 }
484 }
485}