1use super::error::KcpSegmentBuildError;
4use super::segment::{KCP_SEGMENT_HEADER_LEN, KcpSegmentMut};
5use super::types::{
6 KcpCommand, KcpConversationId, KcpFragment, KcpSequenceNumber, KcpTimestamp, KcpUnacknowledged,
7};
8
9pub struct KcpSegmentBuilder<'a, 'b> {
11 destination: &'a mut [u8],
12 conversation_id: KcpConversationId,
13 command: KcpCommand,
14 payload: &'b [u8],
15 fragment: KcpFragment,
16 window_size: u16,
17 timestamp: KcpTimestamp,
18 sequence_number: KcpSequenceNumber,
19 unacknowledged: KcpUnacknowledged,
20}
21
22impl<'a, 'b> KcpSegmentBuilder<'a, 'b> {
23 pub fn new(
25 destination: &'a mut [u8],
26 conversation_id: KcpConversationId,
27 command: KcpCommand,
28 payload: &'b [u8],
29 ) -> Self {
30 Self {
31 destination,
32 conversation_id,
33 command,
34 payload,
35 fragment: KcpFragment::new(0),
36 window_size: 0,
37 timestamp: KcpTimestamp::new(0),
38 sequence_number: KcpSequenceNumber::new(0),
39 unacknowledged: KcpUnacknowledged::new(0),
40 }
41 }
42
43 pub fn fragment(mut self, value: KcpFragment) -> Self {
45 self.fragment = value;
46 self
47 }
48
49 pub fn window_size(mut self, value: u16) -> Self {
51 self.window_size = value;
52 self
53 }
54
55 pub fn timestamp(mut self, value: KcpTimestamp) -> Self {
57 self.timestamp = value;
58 self
59 }
60
61 pub fn sequence_number(mut self, value: KcpSequenceNumber) -> Self {
63 self.sequence_number = value;
64 self
65 }
66
67 pub fn unacknowledged(mut self, value: KcpUnacknowledged) -> Self {
69 self.unacknowledged = value;
70 self
71 }
72
73 pub fn build(self) -> Result<KcpSegmentMut<'a>, KcpSegmentBuildError> {
75 let payload_length = self.payload.len();
76 let encoded_payload_length = u32::try_from(payload_length).map_err(|_| {
77 KcpSegmentBuildError::PayloadLengthTooLarge {
78 length: payload_length,
79 }
80 })?;
81 let segment_length = KCP_SEGMENT_HEADER_LEN.checked_add(payload_length).ok_or(
82 KcpSegmentBuildError::LengthOverflow {
83 header_length: KCP_SEGMENT_HEADER_LEN,
84 payload_length,
85 },
86 )?;
87 if self.destination.len() < segment_length {
88 return Err(KcpSegmentBuildError::BufferTooShort {
89 required: segment_length,
90 available: self.destination.len(),
91 });
92 }
93
94 let bytes = &mut self.destination[..segment_length];
95 bytes[0..4].copy_from_slice(&self.conversation_id.raw().to_le_bytes());
96 bytes[4] = self.command.raw();
97 bytes[5] = self.fragment.raw();
98 bytes[6..8].copy_from_slice(&self.window_size.to_le_bytes());
99 bytes[8..12].copy_from_slice(&self.timestamp.raw().to_le_bytes());
100 bytes[12..16].copy_from_slice(&self.sequence_number.raw().to_le_bytes());
101 bytes[16..20].copy_from_slice(&self.unacknowledged.raw().to_le_bytes());
102 bytes[20..24].copy_from_slice(&encoded_payload_length.to_le_bytes());
103 bytes[KCP_SEGMENT_HEADER_LEN..].copy_from_slice(self.payload);
104 Ok(KcpSegmentMut::from_validated(bytes))
105 }
106}