s2n_quic_transport/endpoint/
packet_buffer.rs1use bytes::{Bytes, BytesMut};
5use s2n_codec::{Encoder, EncoderBuffer};
6use s2n_quic_core::path::MINIMUM_MAX_DATAGRAM_SIZE;
7
8#[derive(Debug)]
12pub struct Buffer {
13 buffer: BytesMut,
14 max_size: usize,
15 count: usize,
16}
17
18const DEFAULT_PACKETS: usize = 64;
22
23impl Default for Buffer {
24 fn default() -> Self {
25 Self {
26 buffer: BytesMut::new(),
27 max_size: MINIMUM_MAX_DATAGRAM_SIZE as usize,
28 count: DEFAULT_PACKETS,
29 }
30 }
31}
32
33impl Buffer {
34 pub fn write<F: FnOnce(EncoderBuffer) -> EncoderBuffer>(
35 &mut self,
36 on_write: F,
37 ) -> Option<Bytes> {
38 let max_size = self.max_size;
39
40 if self.buffer.capacity() < max_size {
41 let len = max_size * self.count;
42 let mut buffer = BytesMut::with_capacity(len);
43 unsafe {
49 buffer.set_len(len);
52 }
53 self.buffer = buffer;
54 }
55
56 let buffer = EncoderBuffer::new(&mut self.buffer[..max_size]);
57
58 let new_buff = on_write(buffer);
59
60 let len = max_size - new_buff.remaining_capacity();
61
62 if len == 0 {
63 return None;
64 }
65
66 debug_assert!(len <= max_size);
67
68 Some(self.buffer.split_to(len).freeze())
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn empty_test() {
78 let mut buffer = Buffer::default();
79 assert_eq!(buffer.buffer.capacity(), 0);
80
81 assert!(
82 buffer.write(|buffer| buffer).is_none(),
83 "empty writes should return None"
84 );
85
86 assert!(buffer.buffer.capacity() > 0);
87 }
88
89 #[test]
90 fn non_empty_test() {
91 let mut buffer = Buffer::default();
92
93 let packet = buffer
94 .write(|mut buffer| {
95 assert_eq!(
96 buffer.remaining_capacity(),
97 MINIMUM_MAX_DATAGRAM_SIZE as usize,
98 "the provider buffer should be the MINIMUM_MAX_DATAGRAM_SIZE"
99 );
100 buffer.encode(&1337u16);
101 buffer
102 })
103 .expect("non-empty writes should return a packet");
104
105 assert_eq!(packet, 1337u16.to_be_bytes()[..]);
106
107 assert!(buffer.buffer.capacity() > 0);
108 assert!(
109 buffer.buffer.capacity() < MINIMUM_MAX_DATAGRAM_SIZE as usize * DEFAULT_PACKETS,
110 "space should be trimmed off for the returned packet"
111 );
112 }
113}