1use super::datagram::{HEADER_LENGTH, UdpDatagramMut};
4use core::fmt;
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub enum UdpDatagramBuildError {
9 MissingDestinationPort,
11 DatagramLengthTooLarge,
13 BufferTooShort {
15 required: usize,
17 available: usize,
19 },
20}
21impl fmt::Display for UdpDatagramBuildError {
22 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 Self::MissingDestinationPort => formatter.write_str("missing UDP destination port"),
25 Self::DatagramLengthTooLarge => {
26 formatter.write_str("UDP datagram length exceeds u16::MAX")
27 }
28 Self::BufferTooShort {
29 required,
30 available,
31 } => write!(
32 formatter,
33 "UDP buffer is too short: need {required} bytes, have {available}"
34 ),
35 }
36 }
37}
38
39pub struct UdpDatagramBuilder<'a> {
41 buffer: &'a mut [u8],
42 payload_length: usize,
43 source_port: u16,
44 destination_port: Option<u16>,
45 checksum: u16,
46}
47impl<'a> UdpDatagramBuilder<'a> {
48 #[inline]
50 pub fn new(buffer: &'a mut [u8], payload_length: usize) -> Self {
51 Self {
52 buffer,
53 payload_length,
54 source_port: 0,
55 destination_port: None,
56 checksum: 0,
57 }
58 }
59 #[inline]
61 pub fn source_port(mut self, value: u16) -> Self {
62 self.source_port = value;
63 self
64 }
65 #[inline]
67 pub fn destination_port(mut self, value: u16) -> Self {
68 self.destination_port = Some(value);
69 self
70 }
71 #[inline]
73 pub fn checksum(mut self, value: u16) -> Self {
74 self.checksum = value;
75 self
76 }
77 pub fn build(self) -> Result<UdpDatagramMut<'a>, UdpDatagramBuildError> {
79 let destination_port = self
80 .destination_port
81 .ok_or(UdpDatagramBuildError::MissingDestinationPort)?;
82 let length = HEADER_LENGTH
83 .checked_add(self.payload_length)
84 .ok_or(UdpDatagramBuildError::DatagramLengthTooLarge)?;
85 let encoded_length =
86 u16::try_from(length).map_err(|_| UdpDatagramBuildError::DatagramLengthTooLarge)?;
87 if self.buffer.len() < length {
88 return Err(UdpDatagramBuildError::BufferTooShort {
89 required: length,
90 available: self.buffer.len(),
91 });
92 }
93 let bytes = &mut self.buffer[..length];
94 bytes[0..2].copy_from_slice(&self.source_port.to_be_bytes());
95 bytes[2..4].copy_from_slice(&destination_port.to_be_bytes());
96 bytes[4..6].copy_from_slice(&encoded_length.to_be_bytes());
97 bytes[6..8].copy_from_slice(&self.checksum.to_be_bytes());
98 Ok(UdpDatagramMut::from_validated(bytes))
99 }
100}