1use crate::error::ParseError;
4
5pub(super) const HEADER_LENGTH: usize = 8;
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub struct UdpDatagram<'a> {
10 bytes: &'a [u8],
11}
12
13impl<'a> UdpDatagram<'a> {
14 pub fn parse(bytes: &'a [u8]) -> Result<Self, ParseError> {
16 let length = validated_length(bytes)?;
17 Ok(Self {
18 bytes: &bytes[..length],
19 })
20 }
21
22 #[inline]
24 pub fn source_port(&self) -> u16 {
25 u16::from_be_bytes([self.bytes[0], self.bytes[1]])
26 }
27 #[inline]
29 pub fn destination_port(&self) -> u16 {
30 u16::from_be_bytes([self.bytes[2], self.bytes[3]])
31 }
32 #[inline]
34 pub fn length(&self) -> u16 {
35 u16::from_be_bytes([self.bytes[4], self.bytes[5]])
36 }
37 #[inline]
39 pub fn checksum(&self) -> u16 {
40 u16::from_be_bytes([self.bytes[6], self.bytes[7]])
41 }
42 #[inline]
44 pub fn payload(&self) -> &'a [u8] {
45 &self.bytes[HEADER_LENGTH..]
46 }
47 #[inline]
49 pub fn as_bytes(&self) -> &'a [u8] {
50 self.bytes
51 }
52}
53
54#[derive(Debug, Eq, PartialEq)]
56pub struct UdpDatagramMut<'a> {
57 bytes: &'a mut [u8],
58}
59
60impl<'a> UdpDatagramMut<'a> {
61 pub fn parse(bytes: &'a mut [u8]) -> Result<Self, ParseError> {
63 let length = validated_length(bytes)?;
64 Ok(Self {
65 bytes: &mut bytes[..length],
66 })
67 }
68
69 pub(crate) fn from_validated(bytes: &'a mut [u8]) -> Self {
70 Self { bytes }
71 }
72
73 #[inline]
75 pub fn source_port(&self) -> u16 {
76 u16::from_be_bytes([self.bytes[0], self.bytes[1]])
77 }
78 #[inline]
80 pub fn destination_port(&self) -> u16 {
81 u16::from_be_bytes([self.bytes[2], self.bytes[3]])
82 }
83 #[inline]
85 pub fn length(&self) -> u16 {
86 u16::from_be_bytes([self.bytes[4], self.bytes[5]])
87 }
88 #[inline]
90 pub fn checksum(&self) -> u16 {
91 u16::from_be_bytes([self.bytes[6], self.bytes[7]])
92 }
93 #[inline]
95 pub fn payload(&self) -> &[u8] {
96 &self.bytes[HEADER_LENGTH..]
97 }
98 #[inline]
100 pub fn payload_mut(&mut self) -> &mut [u8] {
101 &mut self.bytes[HEADER_LENGTH..]
102 }
103 #[inline]
105 pub fn as_bytes(&self) -> &[u8] {
106 self.bytes
107 }
108 #[inline]
110 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
111 self.bytes
112 }
113 #[inline]
115 pub fn set_source_port(&mut self, value: u16) {
116 self.bytes[0..2].copy_from_slice(&value.to_be_bytes());
117 }
118 #[inline]
120 pub fn set_destination_port(&mut self, value: u16) {
121 self.bytes[2..4].copy_from_slice(&value.to_be_bytes());
122 }
123 #[inline]
125 pub fn set_checksum(&mut self, value: u16) {
126 self.bytes[6..8].copy_from_slice(&value.to_be_bytes());
127 }
128}
129
130fn validated_length(bytes: &[u8]) -> Result<usize, ParseError> {
131 if bytes.len() < HEADER_LENGTH {
132 return Err(ParseError::Truncated {
133 minimum: HEADER_LENGTH,
134 available: bytes.len(),
135 });
136 }
137 let length = usize::from(u16::from_be_bytes([bytes[4], bytes[5]]));
138 if length == 0 || length < HEADER_LENGTH {
139 return Err(ParseError::InvalidTotalLength {
140 header_length: HEADER_LENGTH,
141 total_length: length,
142 });
143 }
144 if bytes.len() < length {
145 return Err(ParseError::Truncated {
146 minimum: length,
147 available: bytes.len(),
148 });
149 }
150 Ok(length)
151}