1use std::sync::Arc;
2
3use crate::{
4 FrameBuffer, HELP_TEXT, Parser,
5 original::{
6 HELP_PATTERN, OFFSET_PATTERN, PB_PATTERN, PX_PATTERN, SIZE_PATTERN,
7 parse_pixel_coordinates, simd_unhex,
8 },
9};
10
11const PARSER_LOOKAHEAD: usize = "PX 1234 1234 rrggbbaa\n".len(); pub struct RefactoredParser<FB: FrameBuffer> {
14 connection_x_offset: usize,
15 connection_y_offset: usize,
16 fb: Arc<FB>,
17}
18
19impl<FB: FrameBuffer> RefactoredParser<FB> {
20 pub fn new(fb: Arc<FB>) -> Self {
21 Self {
22 connection_x_offset: 0,
23 connection_y_offset: 0,
24 fb,
25 }
26 }
27
28 #[inline(always)]
29 fn handle_pixel(
30 &self,
31 buffer: &[u8],
32 mut idx: usize,
33 response: &mut Vec<u8>,
34 ) -> (usize, usize) {
35 let previous = idx;
36 idx += 3;
37
38 let (mut x, mut y, present) = parse_pixel_coordinates(buffer.as_ptr(), &mut idx);
39
40 if present {
41 x += self.connection_x_offset;
42 y += self.connection_y_offset;
43
44 if unsafe { *buffer.get_unchecked(idx) } == b' ' {
46 idx += 1;
47
48 if unsafe { *buffer.get_unchecked(idx + 6) } == b'\n' {
53 idx += 7;
54 self.handle_rgb(idx, buffer, x, y);
55 (idx, idx)
56 }
57 else if unsafe { *buffer.get_unchecked(idx + 8) } == b'\n' {
59 idx += 9;
60 self.handle_rgba(idx, buffer, x, y);
61 (idx, idx)
62 }
63 else if unsafe { *buffer.get_unchecked(idx + 2) } == b'\n' {
65 idx += 3;
66 self.handle_gray(idx, buffer, x, y);
67 (idx, idx)
68 } else {
69 (idx, previous)
70 }
71 }
72 else if unsafe { *buffer.get_unchecked(idx) } == b'\n' {
74 idx += 1;
75 self.handle_get_pixel(response, x, y);
76 (idx, idx)
77 } else {
78 (idx, previous)
79 }
80 } else {
81 (idx, previous)
82 }
83 }
84
85 #[inline(always)]
86 fn handle_binary_pixel(&self, buffer: &[u8], mut idx: usize) -> (usize, usize) {
87 let previous = idx;
88 idx += 2;
89
90 let command_bytes = unsafe { (buffer.as_ptr().add(idx) as *const u64).read_unaligned() };
91
92 let x = u16::from_le((command_bytes) as u16);
93 let y = u16::from_le((command_bytes >> 16) as u16);
94 let rgba = u32::from_le((command_bytes >> 32) as u32);
95
96 self.fb.set(x as usize, y as usize, rgba & 0x00ff_ffff);
98
99 idx += 8;
100 (idx, previous)
101 }
102
103 #[inline(always)]
104 fn handle_offset(&mut self, idx: &mut usize, buffer: &[u8]) {
105 let (x, y, present) = parse_pixel_coordinates(buffer.as_ptr(), idx);
106
107 if present && unsafe { *buffer.get_unchecked(*idx) } == b'\n' {
109 self.connection_x_offset = x;
110 self.connection_y_offset = y;
111 }
112 }
113
114 #[inline(always)]
115 fn handle_size(&self, response: &mut Vec<u8>) {
116 response.extend_from_slice(
117 format!("SIZE {} {}\n", self.fb.get_width(), self.fb.get_height()).as_bytes(),
118 );
119 }
120
121 #[inline(always)]
122 fn handle_help(&self, response: &mut Vec<u8>) {
123 response.extend_from_slice(HELP_TEXT);
124 }
125
126 #[inline(always)]
127 fn handle_rgb(&self, idx: usize, buffer: &[u8], x: usize, y: usize) {
128 let rgba: u32 = simd_unhex(unsafe { buffer.as_ptr().add(idx - 7) });
129
130 self.fb.set(x, y, rgba & 0x00ff_ffff);
131 }
132
133 #[cfg(not(feature = "alpha"))]
134 #[inline(always)]
135 fn handle_rgba(&self, idx: usize, buffer: &[u8], x: usize, y: usize) {
136 let rgba: u32 = simd_unhex(unsafe { buffer.as_ptr().add(idx - 9) });
137
138 self.fb.set(x, y, rgba & 0x00ff_ffff);
139 }
140
141 #[cfg(feature = "alpha")]
142 #[inline(always)]
143 fn handle_rgba(&self, idx: usize, buffer: &[u8], x: usize, y: usize) {
144 let rgba: u32 = simd_unhex(unsafe { buffer.as_ptr().add(idx - 9) });
145
146 let alpha = (rgba >> 24) & 0xff;
147
148 if alpha == 0 || x >= self.fb.get_width() || y >= self.fb.get_height() {
149 return;
150 }
151
152 let alpha_comp = 0xff - alpha;
153 let current = unsafe { self.fb.get_unchecked(x, y) };
154 let r = (rgba >> 16) & 0xff;
155 let g = (rgba >> 8) & 0xff;
156 let b = rgba & 0xff;
157
158 let r: u32 = (((current >> 24) & 0xff) * alpha_comp + r * alpha) / 0xff;
159 let g: u32 = (((current >> 16) & 0xff) * alpha_comp + g * alpha) / 0xff;
160 let b: u32 = (((current >> 8) & 0xff) * alpha_comp + b * alpha) / 0xff;
161
162 self.fb.set(x, y, (r << 16) | (g << 8) | b);
163 }
164
165 #[inline(always)]
166 fn handle_gray(&self, idx: usize, buffer: &[u8], x: usize, y: usize) {
167 let base: u32 = simd_unhex(unsafe { buffer.as_ptr().add(idx - 3) }) & 0xff;
170
171 let rgba: u32 = (base << 16) | (base << 8) | base;
172
173 self.fb.set(x, y, rgba);
174 }
175
176 #[inline(always)]
177 fn handle_get_pixel(&self, response: &mut Vec<u8>, x: usize, y: usize) {
178 if let Some(rgb) = self.fb.get(x, y) {
179 response.extend_from_slice(
180 format!(
181 "PX {} {} {:06x}\n",
182 x - self.connection_x_offset,
184 y - self.connection_y_offset,
185 rgb.to_be() >> 8
186 )
187 .as_bytes(),
188 );
189 }
190 }
191}
192
193impl<FB: FrameBuffer> Parser for RefactoredParser<FB> {
194 fn parse(&mut self, buffer: &[u8], response: &mut Vec<u8>) -> usize {
195 let mut last_byte_parsed = 0;
196
197 let mut i = 0; let loop_end = buffer.len().saturating_sub(PARSER_LOOKAHEAD); while i < loop_end {
201 let current_command =
202 unsafe { (buffer.as_ptr().add(i) as *const u64).read_unaligned() };
203 if current_command & 0x00ff_ffff == PX_PATTERN {
204 (i, last_byte_parsed) = self.handle_pixel(buffer, i, response);
205 } else if cfg!(feature = "binary-set-pixel")
206 && current_command & 0x0000_ffff == PB_PATTERN
207 {
208 (i, last_byte_parsed) = self.handle_binary_pixel(buffer, i);
209 } else if current_command & 0x00ff_ffff_ffff_ffff == OFFSET_PATTERN {
210 i += 7;
211 self.handle_offset(&mut i, buffer);
212 last_byte_parsed = i;
213 } else if current_command & 0xffff_ffff == SIZE_PATTERN {
214 i += 4;
215 last_byte_parsed = i;
216 self.handle_size(response);
217 } else if current_command & 0xffff_ffff == HELP_PATTERN {
218 i += 4;
219 last_byte_parsed = i;
220 self.handle_help(response);
221 } else {
222 i += 1;
223 }
224 }
225
226 last_byte_parsed.wrapping_sub(1)
227 }
228
229 fn parser_lookahead(&self) -> usize {
230 PARSER_LOOKAHEAD
231 }
232}