1//! Collects X11 data into "packets" to be parsed by a display.
2
3use core::convert::TryInto;
4use core::fmt;
5use core::mem::replace;
6
7use alloc::{vec, vec::Vec};
8
9/// Minimal length of an X11 packet.
10const MINIMAL_PACKET_LENGTH: usize = 32;
11
12/// A wrapper around a buffer used to read X11 packets.
13pub struct PacketReader {
14 /// A partially-read packet.
15 pending_packet: Vec<u8>,
16
17 /// The point at which the packet is already read.
18 already_read: usize,
19}
20
21impl fmt::Debug for PacketReader {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 f&mut DebugTuple<'_, '_>.debug_tuple(name:"PacketReader")
24 .field(&format_args!(
25 "{}/{}",
26 self.already_read,
27 self.pending_packet.len()
28 ))
29 .finish()
30 }
31}
32
33impl Default for PacketReader {
34 fn default() -> Self {
35 Self::new()
36 }
37}
38
39impl PacketReader {
40 /// Create a new, empty `PacketReader`.
41 ///
42 /// # Example
43 ///
44 /// ```rust
45 /// # use x11rb_protocol::packet_reader::PacketReader;
46 /// let reader = PacketReader::new();
47 /// ```
48 pub fn new() -> Self {
49 Self {
50 pending_packet: vec![0; MINIMAL_PACKET_LENGTH],
51 already_read: 0,
52 }
53 }
54
55 /// Get the buffer that the reader should fill with data.
56 ///
57 /// # Example
58 ///
59 /// ```rust
60 /// # use x11rb_protocol::packet_reader::PacketReader;
61 /// # use x11rb_protocol::protocol::xproto::{GetInputFocusReply, InputFocus, Window};
62 /// let mut reader = PacketReader::new();
63 /// let buffer: [u8; 32] = read_in_buffer();
64 ///
65 /// reader.buffer().copy_from_slice(&buffer);
66 ///
67 /// # fn read_in_buffer() -> [u8; 32] { [0; 32] }
68 /// ```
69 pub fn buffer(&mut self) -> &mut [u8] {
70 &mut self.pending_packet[self.already_read..]
71 }
72
73 /// The remaining capacity that needs to be filled.
74 pub fn remaining_capacity(&self) -> usize {
75 self.pending_packet.len() - self.already_read
76 }
77
78 /// Advance this buffer by the given amount.
79 ///
80 /// This will return the packet that was read, if enough bytes were read in order
81 /// to form a complete packet.
82 pub fn advance(&mut self, amount: usize) -> Option<Vec<u8>> {
83 self.already_read += amount;
84 debug_assert!(self.already_read <= self.pending_packet.len());
85
86 if self.already_read == MINIMAL_PACKET_LENGTH {
87 // we've read in the minimal packet, compute the amount of data we need to read
88 // to form a complete packet
89 let extra_length = extra_length(&self.pending_packet);
90
91 // tell if we need to read more
92 if extra_length > 0 {
93 let total_length = MINIMAL_PACKET_LENGTH + extra_length;
94 self.pending_packet.resize(total_length, 0);
95 return None;
96 }
97 } else if self.already_read != self.pending_packet.len() {
98 // we haven't read the full packet yet, return
99 return None;
100 }
101
102 // we've read in the full packet, return it
103 self.already_read = 0;
104 Some(replace(
105 &mut self.pending_packet,
106 vec![0; MINIMAL_PACKET_LENGTH],
107 ))
108 }
109}
110
111/// Compute the length of the data we need to read, beyond the `MINIMAL_PACKET_LENGTH`.
112fn extra_length(buffer: &[u8]) -> usize {
113 use crate::protocol::xproto::GE_GENERIC_EVENT;
114 const REPLY: u8 = 1;
115
116 let response_type: u8 = buffer[0];
117
118 if response_type == REPLY || response_type & 0x7f == GE_GENERIC_EVENT {
119 let length_field: [u8; 4] = buffer[4..8].try_into().unwrap();
120 let length_field: usize = u32::from_ne_bytes(length_field) as usize;
121 4 * length_field
122 } else {
123 // Fixed size packet: error or event that is not GE_GENERIC_EVENT
124 0
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::PacketReader;
131 use alloc::{vec, vec::Vec};
132
133 fn test_packets(packets: Vec<Vec<u8>>) {
134 let mut reader = PacketReader::default();
135 for mut packet in packets {
136 let original_packet = packet.clone();
137
138 loop {
139 let buffer = reader.buffer();
140 let amount = std::cmp::min(buffer.len(), packet.len());
141 buffer.copy_from_slice(&packet[..amount]);
142 let _ = packet.drain(..amount);
143
144 if let Some(read_packet) = reader.advance(amount) {
145 assert_eq!(read_packet, original_packet);
146 return;
147 }
148 }
149 }
150 }
151
152 fn make_reply_with_length(len: usize) -> Vec<u8> {
153 let mut packet = vec![0; len];
154 let len = (len - 32) / 4;
155
156 // write "len" to bytes 4..8 in the packet
157 let len_bytes = (len as u32).to_ne_bytes();
158 packet[4..8].copy_from_slice(&len_bytes);
159 packet[0] = 1;
160
161 packet
162 }
163
164 #[test]
165 fn fixed_size_packet() {
166 // packet with a fixed size
167 let packet = vec![0; 32];
168 test_packets(vec![packet]);
169 }
170
171 #[test]
172 fn variable_size_packet() {
173 // packet with a variable size
174 let packet = make_reply_with_length(1200);
175 test_packets(vec![packet]);
176 }
177
178 #[test]
179 fn test_many_fixed_size_packets() {
180 let mut packets = vec![];
181 for _ in 0..100 {
182 packets.push(vec![0; 32]);
183 }
184 test_packets(packets);
185 }
186
187 #[test]
188 fn test_many_variable_size_packets() {
189 let mut packets = vec![];
190 for i in 0..100 {
191 // for maximum variation, increase packet size in a curved parabola
192 // defined by -1/25 (x - 50)^2 + 100
193 let variation = ((i - 50) * (i - 50)) as f32;
194 let variation = -1.0 / 25.0 * variation + 100.0;
195 let variation = variation as usize;
196
197 let mut len = 1200 + variation;
198 let mut packet = vec![0; len];
199 len = (len - 32) / 4;
200
201 // write "len" to bytes 4..8 in the packet
202 let len_bytes = (len as u32).to_ne_bytes();
203 packet[4..8].copy_from_slice(&len_bytes);
204 packet[0] = 1;
205
206 packets.push(packet);
207 }
208 test_packets(packets);
209 }
210
211 #[test]
212 fn test_many_size_packets_mixed() {
213 let mut packets = vec![];
214 for i in 0..100 {
215 // on odds, do a varsize packet
216 let mut len = if i & 1 == 1 {
217 // for maximum variation, increase packet size in a curved parabola
218 // defined by -1/25 (x - 50)^2 + 100
219 let variation = ((i - 50) * (i - 50)) as f32;
220 let variation = -1.0 / 25.0 * variation + 100.0;
221 let variation = variation as usize;
222
223 1200 + variation
224 } else {
225 32
226 };
227 let mut packet = vec![0; len];
228 len = (len - 32) / 4;
229
230 // write "len" to bytes 4..8 in the packet
231 let len_bytes = (len as u32).to_ne_bytes();
232 packet[4..8].copy_from_slice(&len_bytes);
233 packet[0] = 1;
234
235 packets.push(packet);
236 }
237 test_packets(packets);
238 }
239
240 #[test]
241 fn test_debug_fixed_size_packet() {
242 // The debug output includes the length of the packet of the packet and how much was
243 // already read
244 let mut reader = PacketReader::new();
245 assert_eq!(std::format!("{:?}", reader), "PacketReader(0/32)");
246
247 let _ = reader.advance(15);
248 assert_eq!(std::format!("{:?}", reader), "PacketReader(15/32)");
249
250 let _ = reader.advance(15);
251 assert_eq!(std::format!("{:?}", reader), "PacketReader(30/32)");
252
253 let _ = reader.advance(2);
254 assert_eq!(std::format!("{:?}", reader), "PacketReader(0/32)");
255 }
256
257 #[test]
258 fn test_debug_variable_size_packet() {
259 let packet = make_reply_with_length(1200);
260 let mut reader = PacketReader::new();
261
262 let first_len = 32;
263 let second_len = 3;
264
265 reader.buffer()[..first_len].copy_from_slice(&packet[..first_len]);
266 let _ = reader.advance(first_len);
267
268 reader.buffer()[..second_len].copy_from_slice(&packet[..second_len]);
269 let _ = reader.advance(second_len);
270
271 assert_eq!(std::format!("{:?}", reader), "PacketReader(35/1200)");
272 }
273}
274