1use std::iter::Map;
2
3use crate::AsciiControl;
4
5#[derive(Default, Clone, Copy, PartialEq, Eq)]
6pub struct VTIntermediate {
7 data: [u8; 2],
8}
9
10impl VTIntermediate {
11 pub const fn empty() -> Self {
12 Self { data: [0, 0] }
13 }
14
15 pub const fn one(c: u8) -> Self {
16 assert!(c >= 0x20 && c <= 0x2F);
17 Self { data: [c, 0] }
18 }
19
20 pub const fn two(c1: u8, c2: u8) -> Self {
21 assert!(c1 >= 0x20 && c1 <= 0x2F);
22 assert!(c2 >= 0x20 && c2 <= 0x2F);
23 Self { data: [c1, c2] }
24 }
25
26 pub fn has(&self, c: u8) -> bool {
27 self.data[0] == c || self.data[1] == c
28 }
29
30 pub fn clear(&mut self) {
31 self.data[0] = 0;
32 self.data[1] = 0;
33 }
34
35 pub fn is_empty(&self) -> bool {
36 self.data[0] == 0 && self.data[1] == 0
37 }
38
39 pub fn len(&self) -> usize {
40 self.data.iter().filter(|&&c| c != 0).count()
41 }
42
43 #[must_use]
44 pub fn push(&mut self, c: u8) -> bool {
45 if c < 0x20 || c > 0x2F {
46 return false;
47 }
48
49 if self.data[0] == 0 {
50 self.data[0] = c;
51 true
52 } else if self.data[1] == 0 {
53 self.data[1] = c;
54 true
55 } else {
56 false
57 }
58 }
59
60 pub const fn const_eq(&self, other: &Self) -> bool {
61 self.data[0] == other.data[0] && self.data[1] == other.data[1]
62 }
63}
64
65impl std::fmt::Debug for VTIntermediate {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 write!(f, "'")?;
69 for c in self.data.iter() {
70 if *c == 0 {
71 break;
72 }
73 write!(f, "{}", *c as char)?;
74 }
75 write!(f, "'")?;
76 Ok(())
77 }
78}
79
80#[derive(PartialEq, Eq)]
81#[repr(transparent)]
82pub struct ParamBuf<'a> {
83 pub(crate) params: &'a Vec<Vec<u8>>,
84}
85
86impl<'a> IntoIterator for ParamBuf<'a> {
87 type Item = &'a [u8];
88 type IntoIter = Map<std::slice::Iter<'a, Vec<u8>>, fn(&Vec<u8>) -> &[u8]>;
89 fn into_iter(self) -> Self::IntoIter {
90 self.params.iter().map(|p| p.as_slice())
91 }
92}
93
94impl<'b, 'a> IntoIterator for &'b ParamBuf<'a> {
95 type Item = &'a [u8];
96 type IntoIter = Map<std::slice::Iter<'a, Vec<u8>>, fn(&Vec<u8>) -> &[u8]>;
97 fn into_iter(self) -> Self::IntoIter {
98 self.params.iter().map(|p| p.as_slice())
99 }
100}
101
102impl<'a> ParamBuf<'a> {
103 pub fn len(&self) -> usize {
104 self.params.len()
105 }
106
107 pub fn is_empty(&self) -> bool {
108 self.params.is_empty()
109 }
110
111 pub fn to_owned(&self) -> ParamBufOwned {
112 ParamBufOwned {
113 params: self.params.iter().map(|p| p.to_vec()).collect(),
114 }
115 }
116}
117
118pub enum VTEvent<'a> {
119 Raw(&'a [u8]),
121
122 C0(u8),
124
125 Esc {
127 intermediates: VTIntermediate,
128 final_byte: u8,
129 },
130
131 Csi {
133 private: Option<u8>,
134 params: ParamBuf<'a>,
135 intermediates: VTIntermediate,
136 final_byte: u8,
137 },
138
139 Ss3 {
141 intermediates: VTIntermediate,
142 final_byte: u8,
143 },
144
145 DcsStart {
147 priv_prefix: Option<u8>,
148 params: ParamBuf<'a>,
149 intermediates: VTIntermediate,
150 final_byte: u8,
151 },
152 DcsData(&'a [u8]),
153 DcsEnd,
154 DcsCancel,
155
156 OscStart,
158 OscData(&'a [u8]),
159 OscEnd {
160 used_bel: bool,
161 },
162 OscCancel,
163}
164
165impl<'a> std::fmt::Debug for VTEvent<'a> {
166 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167 use VTEvent::*;
168 match self {
169 Raw(s) => {
170 write!(f, "Raw('")?;
171 for chunk in s.utf8_chunks() {
172 for c in chunk.valid().chars() {
173 if let Ok(c) = AsciiControl::try_from(c) {
174 write!(f, "{}", c)?;
175 } else {
176 write!(f, "{}", c)?;
177 }
178 }
179 if !chunk.invalid().is_empty() {
180 write!(f, "<{}>", hex::encode(chunk.invalid()))?;
181 }
182 }
183 write!(f, "')")?;
184 Ok(())
185 }
186 C0(b) => write!(f, "C0({:02x})", b),
187 Esc {
188 intermediates,
189 final_byte,
190 } => {
191 write!(f, "Esc({:?}", intermediates)?;
192 write!(f, ", {})", *final_byte as char)?;
193 Ok(())
194 }
195 Csi {
196 private,
197 params,
198 intermediates,
199 final_byte,
200 } => {
201 write!(f, "Csi(")?;
202 if let Some(p) = private {
203 write!(f, "{:?}", *p as char)?;
204 }
205 for param in params {
206 write!(f, ", '")?;
207 for chunk in param.utf8_chunks() {
208 write!(f, "{}", chunk.valid())?;
209 if !chunk.invalid().is_empty() {
210 write!(f, "<{}>", hex::encode(chunk.invalid()))?;
211 }
212 }
213 write!(f, "'")?;
214 }
215 write!(f, ", {:?}", intermediates)?;
216 write!(f, ", {:?})", *final_byte as char)?;
217 Ok(())
218 }
219 Ss3 {
220 intermediates,
221 final_byte,
222 } => {
223 write!(f, "Ss3(")?;
224 write!(f, "{:?}", intermediates)?;
225 write!(f, ", {})", *final_byte as char)?;
226 Ok(())
227 }
228 DcsStart {
229 priv_prefix,
230 params,
231 intermediates,
232 final_byte,
233 } => {
234 write!(f, "DcsStart(")?;
235 if let Some(p) = priv_prefix {
236 write!(f, "{:?}", *p as char)?;
237 }
238 for param in params {
239 write!(f, ", '")?;
240 for chunk in param.utf8_chunks() {
241 write!(f, "{}", chunk.valid())?;
242 if !chunk.invalid().is_empty() {
243 write!(f, "<{}>", hex::encode(chunk.invalid()))?;
244 }
245 }
246 write!(f, "'")?;
247 }
248 write!(f, ", {:?}", intermediates)?;
249 write!(f, ", {})", *final_byte as char)?;
250 Ok(())
251 }
252 DcsData(s) => {
253 write!(f, "DcsData('")?;
254 for chunk in s.utf8_chunks() {
255 for c in chunk.valid().chars() {
256 if let Ok(c) = AsciiControl::try_from(c) {
257 write!(f, "{}", c)?;
258 } else {
259 write!(f, "{}", c)?;
260 }
261 }
262 if !chunk.invalid().is_empty() {
263 write!(f, "<{}>", hex::encode(chunk.invalid()))?;
264 }
265 }
266 write!(f, "')")?;
267 Ok(())
268 }
269 DcsEnd => write!(f, "DcsEnd"),
270 DcsCancel => write!(f, "DcsCancel"),
271 OscStart => write!(f, "OscStart"),
272 OscData(s) => {
273 write!(f, "OscData('")?;
274 for chunk in s.utf8_chunks() {
275 for c in chunk.valid().chars() {
276 if let Ok(c) = AsciiControl::try_from(c) {
277 write!(f, "{}", c)?;
278 } else {
279 write!(f, "{}", c)?;
280 }
281 }
282 if !chunk.invalid().is_empty() {
283 write!(f, "<{}>", hex::encode(chunk.invalid()))?;
284 }
285 }
286 write!(f, "')")?;
287 Ok(())
288 }
289 OscEnd { .. } => {
290 write!(f, "OscEnd")?;
291 Ok(())
292 }
293 OscCancel => write!(f, "OscCancel"),
294 }
295 }
296}
297
298impl<'a> VTEvent<'a> {
299 pub fn to_owned(&self) -> VTOwnedEvent {
300 use VTEvent::*;
301 match self {
302 Raw(s) => VTOwnedEvent::Raw(s.to_vec()),
303 C0(b) => VTOwnedEvent::C0(*b),
304 Esc {
305 intermediates,
306 final_byte,
307 } => VTOwnedEvent::Esc {
308 intermediates: intermediates.clone(),
309 final_byte: *final_byte,
310 },
311 Csi {
312 private,
313 params,
314 intermediates,
315 final_byte,
316 } => VTOwnedEvent::Csi {
317 private: private.clone(),
318 params: params.to_owned(),
319 intermediates: intermediates.clone(),
320 final_byte: *final_byte,
321 },
322 Ss3 {
323 intermediates,
324 final_byte,
325 } => VTOwnedEvent::Ss3 {
326 intermediates: intermediates.clone(),
327 final_byte: *final_byte,
328 },
329 DcsStart {
330 priv_prefix,
331 params,
332 intermediates,
333 final_byte,
334 } => VTOwnedEvent::DcsStart {
335 priv_prefix: priv_prefix.clone(),
336 params: params.to_owned(),
337 intermediates: intermediates.clone(),
338 final_byte: *final_byte,
339 },
340 DcsData(s) => VTOwnedEvent::DcsData(s.to_vec()),
341 DcsEnd => VTOwnedEvent::DcsEnd,
342 DcsCancel => VTOwnedEvent::DcsCancel,
343 OscStart => VTOwnedEvent::OscStart,
344 OscData(s) => VTOwnedEvent::OscData(s.to_vec()),
345 OscEnd { used_bel } => VTOwnedEvent::OscEnd {
346 used_bel: *used_bel,
347 },
348 OscCancel => VTOwnedEvent::OscCancel,
349 }
350 }
351}
352
353#[derive(Clone, PartialEq, Eq)]
354pub struct ParamBufOwned {
355 pub(crate) params: Vec<Vec<u8>>,
356}
357
358impl IntoIterator for ParamBufOwned {
359 type Item = Vec<u8>;
360 type IntoIter = std::vec::IntoIter<Vec<u8>>;
361 fn into_iter(self) -> Self::IntoIter {
362 self.params.into_iter()
363 }
364}
365
366impl<'b> IntoIterator for &'b ParamBufOwned {
367 type Item = &'b [u8];
368 type IntoIter = Map<std::slice::Iter<'b, Vec<u8>>, fn(&Vec<u8>) -> &[u8]>;
369 fn into_iter(self) -> Self::IntoIter {
370 self.params.iter().map(|p| p.as_slice())
371 }
372}
373
374impl ParamBufOwned {
375 pub fn len(&self) -> usize {
376 self.params.len()
377 }
378
379 pub fn is_empty(&self) -> bool {
380 self.params.is_empty()
381 }
382
383 pub fn borrow(&self) -> ParamBuf<'_> {
384 ParamBuf {
385 params: &self.params,
386 }
387 }
388}
389
390#[derive(Clone, PartialEq, Eq)]
391pub enum VTOwnedEvent {
392 Raw(Vec<u8>),
393 C0(u8),
394 Esc {
395 intermediates: VTIntermediate,
396 final_byte: u8,
397 },
398 Csi {
399 private: Option<u8>,
400 params: ParamBufOwned,
401 intermediates: VTIntermediate,
402 final_byte: u8,
403 },
404 Ss3 {
405 intermediates: VTIntermediate,
406 final_byte: u8,
407 },
408 DcsStart {
409 priv_prefix: Option<u8>,
410 params: ParamBufOwned,
411 intermediates: VTIntermediate,
412 final_byte: u8,
413 },
414 DcsData(Vec<u8>),
415 DcsEnd,
416 DcsCancel,
417 OscStart,
418 OscData(Vec<u8>),
419 OscEnd {
420 used_bel: bool,
421 },
422 OscCancel,
423}
424
425impl std::fmt::Debug for VTOwnedEvent {
426 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
427 self.borrow().fmt(f)
428 }
429}
430
431impl VTOwnedEvent {
432 pub fn borrow(&self) -> VTEvent<'_> {
433 match self {
434 VTOwnedEvent::Raw(s) => VTEvent::Raw(s),
435 VTOwnedEvent::C0(b) => VTEvent::C0(*b),
436 VTOwnedEvent::Esc {
437 intermediates,
438 final_byte,
439 } => VTEvent::Esc {
440 intermediates: intermediates.clone(),
441 final_byte: *final_byte,
442 },
443 VTOwnedEvent::Csi {
444 private,
445 params,
446 intermediates,
447 final_byte,
448 } => VTEvent::Csi {
449 private: private.clone(),
450 params: params.borrow(),
451 intermediates: intermediates.clone(),
452 final_byte: *final_byte,
453 },
454 VTOwnedEvent::Ss3 {
455 intermediates,
456 final_byte,
457 } => VTEvent::Ss3 {
458 intermediates: intermediates.clone(),
459 final_byte: *final_byte,
460 },
461 VTOwnedEvent::DcsStart {
462 priv_prefix,
463 params,
464 intermediates,
465 final_byte,
466 } => VTEvent::DcsStart {
467 priv_prefix: priv_prefix.clone(),
468 params: params.borrow(),
469 intermediates: intermediates.clone(),
470 final_byte: *final_byte,
471 },
472 VTOwnedEvent::DcsData(s) => VTEvent::DcsData(s),
473 VTOwnedEvent::DcsEnd => VTEvent::DcsEnd,
474 VTOwnedEvent::DcsCancel => VTEvent::DcsCancel,
475 VTOwnedEvent::OscStart => VTEvent::OscStart,
476 VTOwnedEvent::OscData(s) => VTEvent::OscData(s),
477 VTOwnedEvent::OscEnd { used_bel } => VTEvent::OscEnd {
478 used_bel: *used_bel,
479 },
480 VTOwnedEvent::OscCancel => VTEvent::OscCancel,
481 }
482 }
483}