1#[cfg(feature = "binary-sync-pixels")]
2use core::slice;
3use std::{
4 simd::{Simd, num::SimdUint, u32x8},
5 sync::Arc,
6};
7
8use crate::{ALT_HELP_TEXT, FrameBuffer, HELP_TEXT, Parser};
9
10pub const PARSER_LOOKAHEAD: usize = "PX 1234 1234 rrggbbaa\n".len(); pub(crate) const PX_PATTERN: u64 = string_to_number(b"PX \0\0\0\0\0");
13pub(crate) const PB_PATTERN: u64 = string_to_number(b"PB\0\0\0\0\0\0");
14pub(crate) const OFFSET_PATTERN: u64 = string_to_number(b"OFFSET \0\0");
15pub(crate) const SIZE_PATTERN: u64 = string_to_number(b"SIZE\0\0\0\0");
16pub(crate) const HELP_PATTERN: u64 = string_to_number(b"HELP\0\0\0\0");
17#[cfg(feature = "binary-sync-pixels")]
18pub(crate) const PXMULTI_PATTERN: u64 = string_to_number(b"PXMULTI\0");
19
20pub struct OriginalParser<FB: FrameBuffer> {
21 connection_x_offset: usize,
22 connection_y_offset: usize,
23 fb: Arc<FB>,
24 #[cfg(feature = "binary-sync-pixels")]
25 remaining_pixel_sync: Option<RemainingPixelSync>,
26}
27
28#[cfg(feature = "binary-sync-pixels")]
29#[derive(Debug)]
30pub struct RemainingPixelSync {
31 current_index: usize,
32 bytes_remaining: usize,
33}
34
35impl<FB: FrameBuffer> OriginalParser<FB> {
36 pub fn new(fb: Arc<FB>) -> Self {
37 Self {
38 connection_x_offset: 0,
39 connection_y_offset: 0,
40 fb,
41 #[cfg(feature = "binary-sync-pixels")]
42 remaining_pixel_sync: None,
43 }
44 }
45}
46
47impl<FB: FrameBuffer> Parser for OriginalParser<FB> {
48 fn parse(&mut self, buffer: &[u8], response: &mut Vec<u8>) -> usize {
49 let mut last_byte_parsed = 0;
50 let mut help_count = 0;
51
52 let mut i = 0; let loop_end = buffer.len().saturating_sub(PARSER_LOOKAHEAD); #[cfg(feature = "binary-sync-pixels")]
56 if let Some(remaining) = &self.remaining_pixel_sync {
57 let buffer = &buffer[0..loop_end];
58
59 if remaining.bytes_remaining <= buffer.len() {
60 self.fb
62 .set_multi_from_start_index(remaining.current_index, unsafe {
63 slice::from_raw_parts(buffer.as_ptr(), remaining.bytes_remaining)
64 });
65 i += remaining.bytes_remaining;
66 last_byte_parsed = i;
67 self.remaining_pixel_sync = None;
68 } else {
69 let pixel_bytes = buffer.len() / 4 * 4;
74
75 let mut index = remaining.current_index;
76 index += self
77 .fb
78 .set_multi_from_start_index(remaining.current_index, unsafe {
79 slice::from_raw_parts(buffer.as_ptr(), pixel_bytes)
80 });
81
82 self.remaining_pixel_sync = Some(RemainingPixelSync {
83 current_index: index,
84 bytes_remaining: remaining.bytes_remaining.saturating_sub(pixel_bytes),
85 });
86
87 return i + pixel_bytes.saturating_sub(1);
91 }
92 }
93
94 while i < loop_end {
95 let current_command =
96 unsafe { (buffer.as_ptr().add(i) as *const u64).read_unaligned() };
97 if current_command & 0x00ff_ffff == PX_PATTERN {
98 i += 3;
99
100 let (mut x, mut y, present) = parse_pixel_coordinates(buffer.as_ptr(), &mut i);
101
102 if present {
103 x += self.connection_x_offset;
104 y += self.connection_y_offset;
105
106 if unsafe { *buffer.get_unchecked(i) } == b' ' {
108 i += 1;
109
110 if unsafe { *buffer.get_unchecked(i + 6) } == b'\n' {
115 last_byte_parsed = i + 6;
116 i += 7; let rgba: u32 = simd_unhex(unsafe { buffer.as_ptr().add(i - 7) });
119
120 self.fb.set(x, y, rgba & 0x00ff_ffff);
121 continue;
122 }
123
124 #[cfg(not(feature = "alpha"))]
126 if unsafe { *buffer.get_unchecked(i + 8) } == b'\n' {
127 last_byte_parsed = i + 8;
128 i += 9; let rgba: u32 = simd_unhex(unsafe { buffer.as_ptr().add(i - 9) });
131
132 self.fb.set(x, y, rgba & 0x00ff_ffff);
133 continue;
134 }
135 #[cfg(feature = "alpha")]
136 if unsafe { *buffer.get_unchecked(i + 8) } == b'\n' {
137 last_byte_parsed = i + 8;
138 i += 9; let rgba = simd_unhex(unsafe { buffer.as_ptr().add(i - 9) });
141
142 let alpha = (rgba >> 24) & 0xff;
143
144 if alpha == 0 || x >= self.fb.get_width() || y >= self.fb.get_height() {
145 continue;
146 }
147
148 let alpha_comp = 0xff - alpha;
149 let current = unsafe { self.fb.get_unchecked(x, y) };
150 let r = (rgba >> 16) & 0xff;
151 let g = (rgba >> 8) & 0xff;
152 let b = rgba & 0xff;
153
154 let r: u32 = (((current >> 24) & 0xff) * alpha_comp + r * alpha) / 0xff;
155 let g: u32 = (((current >> 16) & 0xff) * alpha_comp + g * alpha) / 0xff;
156 let b: u32 = (((current >> 8) & 0xff) * alpha_comp + b * alpha) / 0xff;
157
158 self.fb.set(x, y, (r << 16) | (g << 8) | b);
159 continue;
160 }
161
162 if unsafe { *buffer.get_unchecked(i + 2) } == b'\n' {
164 last_byte_parsed = i + 2;
165 i += 3; let base = simd_unhex(unsafe { buffer.as_ptr().add(i - 3) }) & 0xff;
168
169 let rgba: u32 = (base << 16) | (base << 8) | base;
170
171 self.fb.set(x, y, rgba);
172
173 continue;
174 }
175 }
176
177 if unsafe { *buffer.get_unchecked(i) } == b'\n' {
179 last_byte_parsed = i;
180 i += 1;
181 if let Some(rgb) = self.fb.get(x, y) {
182 response.extend_from_slice(
183 format!(
184 "PX {} {} {:06x}\n",
185 x - self.connection_x_offset,
187 y - self.connection_y_offset,
188 rgb.to_be() >> 8
189 )
190 .as_bytes(),
191 );
192 }
193 continue;
194 }
195 }
196 }
197 #[cfg(feature = "binary-set-pixel")]
198 if current_command & 0x0000_ffff == PB_PATTERN {
199 let command_bytes =
200 unsafe { (buffer.as_ptr().add(i + 2) as *const u64).read_unaligned() };
201
202 let x = u16::from_le((command_bytes) as u16);
203 let y = u16::from_le((command_bytes >> 16) as u16);
204 let rgba = u32::from_le((command_bytes >> 32) as u32);
205
206 self.fb.set(x as usize, y as usize, rgba & 0x00ff_ffff);
208 last_byte_parsed = i + 1 + 2 + 2 + 4;
210 i += 10;
211 continue;
212 }
213 #[cfg(feature = "binary-sync-pixels")]
214 if current_command & 0x00ff_ffff_ffff_ffff == PXMULTI_PATTERN {
215 i += "PXMULTI".len();
216 let header = unsafe { (buffer.as_ptr().add(i) as *const u64).read_unaligned() };
217 i += 8;
218
219 let start_x = u16::from_le((header) as u16);
220 let start_y = u16::from_le((header >> 16) as u16);
221 let len = u32::from_le((header >> 32) as u32);
222 let len_in_bytes = len as usize * 4;
223 let bytes_left_in_buffer = loop_end.saturating_sub(i);
224
225 if len_in_bytes <= bytes_left_in_buffer {
226 self.fb
228 .set_multi(start_x as usize, start_y as usize, unsafe {
229 slice::from_raw_parts(buffer.as_ptr().add(i), len_in_bytes)
230 });
231
232 i += len_in_bytes;
233 last_byte_parsed = i;
234 continue;
235 } else {
236 let pixel_bytes: usize = bytes_left_in_buffer / 4 * 4;
238
239 let mut current_index =
242 start_x as usize + start_y as usize * self.fb.get_width();
243 current_index += self.fb.set_multi_from_start_index(current_index, unsafe {
244 slice::from_raw_parts(buffer.as_ptr().add(i), pixel_bytes)
245 });
246
247 self.remaining_pixel_sync = Some(RemainingPixelSync {
248 current_index,
249 bytes_remaining: len_in_bytes - pixel_bytes,
250 });
251
252 return i + pixel_bytes.saturating_sub(1);
256 }
257 }
258 if current_command & 0x00ff_ffff_ffff_ffff == OFFSET_PATTERN {
259 i += 7;
260
261 let (x, y, present) = parse_pixel_coordinates(buffer.as_ptr(), &mut i);
262
263 if present && unsafe { *buffer.get_unchecked(i) } == b'\n' {
265 last_byte_parsed = i;
266 self.connection_x_offset = x;
267 self.connection_y_offset = y;
268 continue;
269 }
270 }
271 if current_command & 0xffff_ffff == SIZE_PATTERN {
272 i += 4;
273 last_byte_parsed = i + 1;
274
275 response.extend_from_slice(
276 format!("SIZE {} {}\n", self.fb.get_width(), self.fb.get_height()).as_bytes(),
277 );
278 continue;
279 }
280 if current_command & 0xffff_ffff == HELP_PATTERN {
281 i += 4;
282 last_byte_parsed = i + 1;
283
284 match help_count {
285 0..=2 => {
286 response.extend_from_slice(HELP_TEXT);
287 help_count += 1;
288 }
289 3 => {
290 response.extend_from_slice(ALT_HELP_TEXT);
291 help_count += 1;
292 }
293 _ => {
294 }
296 }
297 continue;
298 }
299
300 i += 1;
301 }
302
303 last_byte_parsed
304 }
306
307 fn parser_lookahead(&self) -> usize {
308 PARSER_LOOKAHEAD
309 }
310}
311
312const fn string_to_number(input: &[u8]) -> u64 {
313 ((input[7] as u64) << 56)
314 | ((input[6] as u64) << 48)
315 | ((input[5] as u64) << 40)
316 | ((input[4] as u64) << 32)
317 | ((input[3] as u64) << 24)
318 | ((input[2] as u64) << 16)
319 | ((input[1] as u64) << 8)
320 | (input[0] as u64)
321}
322
323const SHIFT_PATTERN: Simd<u32, 8> = u32x8::from_array([4, 0, 12, 8, 20, 16, 28, 24]);
324const SIMD_6: Simd<u32, 8> = u32x8::from_array([6; 8]);
325const SIMD_F: Simd<u32, 8> = u32x8::from_array([0xf; 8]);
326const SIMD_9: Simd<u32, 8> = u32x8::from_array([9; 8]);
327
328#[inline(always)]
331pub(crate) fn simd_unhex(value: *const u8) -> u32 {
332 let input = unsafe {
334 u32x8::from_array([
335 *value as u32,
336 *value.add(1) as u32,
337 *value.add(2) as u32,
338 *value.add(3) as u32,
339 *value.add(4) as u32,
340 *value.add(5) as u32,
341 *value.add(6) as u32,
342 *value.add(7) as u32,
343 ])
344 };
345 let sr6 = input >> SIMD_6;
347 let and15 = input & SIMD_F;
348 let mul = sr6 * SIMD_9;
349 let hexed = and15 + mul;
350 let shifted = hexed << SHIFT_PATTERN;
351 shifted.reduce_or()
352}
353
354#[inline(always)]
355fn parse_coordinate(buffer: *const u8, current_index: &mut usize) -> (usize, bool) {
356 let digits = unsafe { (buffer.add(*current_index) as *const usize).read_unaligned() };
357
358 let mut result = 0;
359 let mut visited = false;
360 for pos in 0..4 {
362 let digit = (digits >> (pos * 8)) & 0xff;
363 if digit >= b'0' as usize && digit <= b'9' as usize {
364 result = 10 * result + digit - b'0' as usize;
365 *current_index += 1;
366 visited = true;
367 } else {
368 break;
369 }
370 }
371
372 (result, visited)
373}
374
375#[inline(always)]
376pub(crate) fn parse_pixel_coordinates(
377 buffer: *const u8,
378 current_index: &mut usize,
379) -> (usize, usize, bool) {
380 let (x, x_visited) = parse_coordinate(buffer, current_index);
381 *current_index += 1;
382 let (y, y_visited) = parse_coordinate(buffer, current_index);
383 (x, y, x_visited && y_visited)
384}