1use std::iter::Map;
2
3use smallvec::SmallVec;
4
5use crate::{AsciiControl, BEL, CAN, CSI, DCS, ESC, OSC, SS2, SS3, ST_FINAL};
6
7#[derive(Default, Clone, Copy, PartialEq, Eq)]
8pub struct VTIntermediate {
9 data: [u8; 2],
10}
11
12impl VTIntermediate {
13 pub const fn empty() -> Self {
14 Self { data: [0, 0] }
15 }
16
17 pub const fn one(c: u8) -> Self {
18 assert!(c >= 0x20 && c <= 0x2F);
19 Self { data: [c, 0] }
20 }
21
22 pub const fn two(c1: u8, c2: u8) -> Self {
23 assert!(c1 >= 0x20 && c1 <= 0x2F);
24 assert!(c2 >= 0x20 && c2 <= 0x2F);
25 Self { data: [c1, c2] }
26 }
27
28 pub fn has(&self, c: u8) -> bool {
29 self.data[0] == c || self.data[1] == c
30 }
31
32 pub fn clear(&mut self) {
33 self.data[0] = 0;
34 self.data[1] = 0;
35 }
36
37 pub fn is_empty(&self) -> bool {
38 self.data[0] == 0 && self.data[1] == 0
39 }
40
41 pub fn len(&self) -> usize {
42 self.data.iter().filter(|&&c| c != 0).count()
43 }
44
45 #[must_use]
46 pub fn push(&mut self, c: u8) -> bool {
47 if c < 0x20 || c > 0x2F {
48 return false;
49 }
50
51 if self.data[0] == c {
53 return false;
54 }
55
56 if self.data[0] == 0 {
57 self.data[0] = c;
58 true
59 } else if self.data[1] == 0 {
60 self.data[1] = c;
61 true
62 } else {
63 false
64 }
65 }
66
67 pub const fn const_eq(&self, other: &Self) -> bool {
68 self.data[0] == other.data[0] && self.data[1] == other.data[1]
69 }
70
71 pub fn byte_len(&self) -> usize {
72 self.data.iter().filter(|&&c| c != 0).count()
73 }
74}
75
76impl std::fmt::Debug for VTIntermediate {
77 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78 write!(f, "'")?;
80 for c in self.data.iter() {
81 if *c == 0 {
82 break;
83 }
84 write!(f, "{}", *c as char)?;
85 }
86 write!(f, "'")?;
87 Ok(())
88 }
89}
90
91pub(crate) type Param = SmallVec<[u8; 32]>;
92pub(crate) type Params = SmallVec<[Param; 8]>;
93
94#[derive(Copy, Clone, PartialEq, Eq)]
95#[repr(transparent)]
96pub struct ParamBuf<'a> {
97 pub(crate) params: &'a Params,
98}
99
100impl<'a> IntoIterator for ParamBuf<'a> {
101 type Item = &'a [u8];
102 type IntoIter = Map<std::slice::Iter<'a, Param>, fn(&Param) -> &[u8]>;
103 fn into_iter(self) -> Self::IntoIter {
104 self.params.iter().map(|p| p.as_slice())
105 }
106}
107
108impl<'b, 'a> IntoIterator for &'b ParamBuf<'a> {
109 type Item = &'a [u8];
110 type IntoIter = Map<std::slice::Iter<'a, Param>, fn(&Param) -> &[u8]>;
111 fn into_iter(self) -> Self::IntoIter {
112 self.params.iter().map(|p| p.as_slice())
113 }
114}
115
116impl<'a> ParamBuf<'a> {
117 pub fn len(&self) -> usize {
118 self.params.len()
119 }
120
121 pub fn is_empty(&self) -> bool {
122 self.params.is_empty()
123 }
124
125 pub fn get(&self, index: usize) -> Option<&[u8]> {
126 self.params.get(index).map(|p| p.as_slice())
127 }
128
129 pub fn try_parse<T: std::str::FromStr>(&self, index: usize) -> Option<T> {
130 self.params.get(index).and_then(|p| {
131 std::str::from_utf8(p.as_slice())
132 .ok()
133 .and_then(|s| s.parse::<T>().ok())
134 })
135 }
136
137 pub fn to_owned(&self) -> ParamBufOwned {
138 ParamBufOwned {
139 params: self.params.iter().map(|p| p.clone()).collect(),
140 }
141 }
142
143 pub fn byte_len(&self) -> usize {
144 self.params.iter().map(|p| p.len()).sum::<usize>() + self.params.len().saturating_sub(1)
145 }
146}
147
148pub enum VTEvent<'a> {
149 Raw(&'a [u8]),
151
152 C0(u8),
154
155 Esc {
157 intermediates: VTIntermediate,
158 final_byte: u8,
159 },
160
161 Ss2 {
163 char: u8,
164 },
165
166 Ss3 {
168 char: u8,
169 },
170
171 Csi {
173 private: Option<u8>,
174 params: ParamBuf<'a>,
175 intermediates: VTIntermediate,
176 final_byte: u8,
177 },
178
179 DcsStart {
181 private: Option<u8>,
182 params: ParamBuf<'a>,
183 intermediates: VTIntermediate,
184 final_byte: u8,
185 },
186 DcsData(&'a [u8]),
187 DcsEnd,
188 DcsCancel,
189
190 OscStart,
192 OscData(&'a [u8]),
193 OscEnd {
194 used_bel: bool,
196 },
197 OscCancel,
198}
199
200impl<'a> std::fmt::Debug for VTEvent<'a> {
201 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202 use VTEvent::*;
203 match self {
204 Raw(s) => {
205 write!(f, "Raw('")?;
206 for chunk in s.utf8_chunks() {
207 for c in chunk.valid().chars() {
208 if let Ok(c) = AsciiControl::try_from(c) {
209 write!(f, "{}", c)?;
210 } else {
211 write!(f, "{}", c)?;
212 }
213 }
214 if !chunk.invalid().is_empty() {
215 write!(f, "<{}>", hex::encode(chunk.invalid()))?;
216 }
217 }
218 write!(f, "')")?;
219 Ok(())
220 }
221 C0(b) => write!(f, "C0({:02x})", b),
222 Esc {
223 intermediates,
224 final_byte,
225 } => {
226 write!(f, "Esc({:?}", intermediates)?;
227 write!(f, ", {})", *final_byte as char)?;
228 Ok(())
229 }
230 Ss2 { char } => write!(f, "Ss2({:?})", *char as char),
231 Ss3 { char } => write!(f, "Ss3({:?})", *char as char),
232 Csi {
233 private,
234 params,
235 intermediates,
236 final_byte,
237 } => {
238 write!(f, "Csi(")?;
239 if let Some(p) = private {
240 write!(f, "{:?}", *p as char)?;
241 }
242 for param in params {
243 write!(f, ", '")?;
244 for chunk in param.utf8_chunks() {
245 write!(f, "{}", chunk.valid())?;
246 if !chunk.invalid().is_empty() {
247 write!(f, "<{}>", hex::encode(chunk.invalid()))?;
248 }
249 }
250 write!(f, "'")?;
251 }
252 write!(f, ", {:?}", intermediates)?;
253 write!(f, ", {:?})", *final_byte as char)?;
254 Ok(())
255 }
256 DcsStart {
257 private,
258 params,
259 intermediates,
260 final_byte,
261 } => {
262 write!(f, "DcsStart(")?;
263 if let Some(p) = private {
264 write!(f, "{:?}", *p as char)?;
265 }
266 for param in params {
267 write!(f, ", '")?;
268 for chunk in param.utf8_chunks() {
269 write!(f, "{}", chunk.valid())?;
270 if !chunk.invalid().is_empty() {
271 write!(f, "<{}>", hex::encode(chunk.invalid()))?;
272 }
273 }
274 write!(f, "'")?;
275 }
276 write!(f, ", {:?}", intermediates)?;
277 write!(f, ", {})", *final_byte as char)?;
278 Ok(())
279 }
280 DcsData(s) => {
281 write!(f, "DcsData('")?;
282 for chunk in s.utf8_chunks() {
283 for c in chunk.valid().chars() {
284 if let Ok(c) = AsciiControl::try_from(c) {
285 write!(f, "{}", c)?;
286 } else {
287 write!(f, "{}", c)?;
288 }
289 }
290 if !chunk.invalid().is_empty() {
291 write!(f, "<{}>", hex::encode(chunk.invalid()))?;
292 }
293 }
294 write!(f, "')")?;
295 Ok(())
296 }
297 DcsEnd => write!(f, "DcsEnd"),
298 DcsCancel => write!(f, "DcsCancel"),
299 OscStart => write!(f, "OscStart"),
300 OscData(s) => {
301 write!(f, "OscData('")?;
302 for chunk in s.utf8_chunks() {
303 for c in chunk.valid().chars() {
304 if let Ok(c) = AsciiControl::try_from(c) {
305 write!(f, "{}", c)?;
306 } else {
307 write!(f, "{}", c)?;
308 }
309 }
310 if !chunk.invalid().is_empty() {
311 write!(f, "<{}>", hex::encode(chunk.invalid()))?;
312 }
313 }
314 write!(f, "')")?;
315 Ok(())
316 }
317 OscEnd { .. } => {
318 write!(f, "OscEnd")?;
319 Ok(())
320 }
321 OscCancel => write!(f, "OscCancel"),
322 }
323 }
324}
325
326impl<'a> VTEvent<'a> {
327 pub fn csi(&self) -> Option<CSI> {
328 match self {
329 VTEvent::Csi {
330 private,
331 params,
332 intermediates,
333 final_byte,
334 } => Some(CSI {
335 private: *private,
336 params: *params,
337 intermediates: intermediates.clone(),
338 final_byte: *final_byte,
339 }),
340 _ => None,
341 }
342 }
343
344 pub fn byte_len(&self) -> usize {
345 use VTEvent::*;
346 let len = match self {
347 Raw(s) => s.len(),
348 C0(_) => 1,
349 Esc { intermediates, .. } => intermediates.len() + 2,
350 Ss2 { .. } => 3,
351 Ss3 { .. } => 3,
352 Csi {
353 private,
354 params,
355 intermediates,
356 ..
357 } => private.is_some() as usize + params.byte_len() + intermediates.byte_len() + 3,
358 DcsStart {
359 private,
360 params,
361 intermediates,
362 ..
363 } => private.is_some() as usize + params.byte_len() + intermediates.byte_len() + 3,
364 DcsData(s) => s.len(),
365 DcsEnd => 2,
366 DcsCancel => 1,
367 OscStart => 2,
368 OscData(s) => s.len(),
369 OscEnd { used_bel } => {
370 if *used_bel {
371 1
372 } else {
373 2
374 }
375 }
376 OscCancel => 1,
377 };
378 len
379 }
380
381 pub fn encode(&self, mut buf: &mut [u8]) -> Result<usize, usize> {
387 use VTEvent::*;
388 let len = self.byte_len();
389
390 if len > buf.len() {
391 return Err(len);
392 }
393
394 match self {
395 Raw(s) | OscData(s) | DcsData(s) => {
396 buf[..s.len()].copy_from_slice(s);
397 }
398 OscCancel | DcsCancel => {
399 buf[0] = CAN;
400 }
401 C0(b) => {
402 buf[0] = *b;
403 }
404 Ss2 { char } => {
405 buf[0] = ESC;
406 buf[1] = SS2;
407 buf[2] = *char;
408 }
409 Ss3 { char } => {
410 buf[0] = ESC;
411 buf[1] = SS3;
412 buf[2] = *char;
413 }
414 Esc {
415 intermediates,
416 final_byte,
417 } => {
418 buf[0] = ESC;
419 buf[1..intermediates.len() + 1]
420 .copy_from_slice(&intermediates.data[..intermediates.len()]);
421 buf[intermediates.len() + 1] = *final_byte;
422 }
423 Csi {
424 private,
425 params,
426 intermediates,
427 final_byte,
428 } => {
429 buf[0] = ESC;
430 buf[1] = CSI;
431 buf = &mut buf[2..];
432 if let Some(p) = private {
433 buf[0] = *p;
434 buf = &mut buf[1..];
435 }
436 let mut params = params.into_iter();
437 if let Some(param) = params.next() {
438 buf[..param.len()].copy_from_slice(param);
439 buf = &mut buf[param.len()..];
440 for param in params {
441 buf[0] = b';';
442 buf = &mut buf[1..];
443 buf[..param.len()].copy_from_slice(param);
444 buf = &mut buf[param.len()..];
445 }
446 }
447 buf[..intermediates.len()]
448 .copy_from_slice(&intermediates.data[..intermediates.len()]);
449 buf[intermediates.len()] = *final_byte;
450 }
451 DcsStart {
452 private,
453 params,
454 intermediates,
455 final_byte,
456 } => {
457 buf[0] = ESC;
458 buf[1] = DCS;
459 buf = &mut buf[2..];
460 if let Some(p) = private {
461 buf[0] = *p;
462 buf = &mut buf[1..];
463 }
464 let mut params = params.into_iter();
465 if let Some(param) = params.next() {
466 buf[..param.len()].copy_from_slice(param);
467 buf = &mut buf[param.len()..];
468 for param in params {
469 buf[0] = b';';
470 buf = &mut buf[1..];
471 buf[..param.len()].copy_from_slice(param);
472 buf = &mut buf[param.len()..];
473 }
474 }
475 buf[..intermediates.len()]
476 .copy_from_slice(&intermediates.data[..intermediates.len()]);
477 buf[intermediates.len()] = *final_byte;
478 }
479 DcsEnd => {
480 buf[0] = ESC;
481 buf[1] = ST_FINAL;
482 }
483 OscStart => {
484 buf[0] = ESC;
485 buf[1] = OSC;
486 }
487 OscEnd { used_bel } => {
488 if *used_bel {
489 buf[0] = BEL;
490 } else {
491 buf[0] = ESC;
492 buf[1] = ST_FINAL
493 }
494 }
495 }
496
497 Ok(len)
498 }
499
500 pub fn to_owned(&self) -> VTOwnedEvent {
501 use VTEvent::*;
502 match self {
503 Raw(s) => VTOwnedEvent::Raw(s.to_vec()),
504 C0(b) => VTOwnedEvent::C0(*b),
505 Esc {
506 intermediates,
507 final_byte,
508 } => VTOwnedEvent::Esc {
509 intermediates: intermediates.clone(),
510 final_byte: *final_byte,
511 },
512 Ss2 { char } => VTOwnedEvent::Ss2 { char: *char },
513 Ss3 { char } => VTOwnedEvent::Ss3 { char: *char },
514 Csi {
515 private,
516 params,
517 intermediates,
518 final_byte,
519 } => VTOwnedEvent::Csi {
520 private: private.clone(),
521 params: params.to_owned(),
522 intermediates: intermediates.clone(),
523 final_byte: *final_byte,
524 },
525 DcsStart {
526 private,
527 params,
528 intermediates,
529 final_byte,
530 } => VTOwnedEvent::DcsStart {
531 private: private.clone(),
532 params: params.to_owned(),
533 intermediates: intermediates.clone(),
534 final_byte: *final_byte,
535 },
536 DcsData(s) => VTOwnedEvent::DcsData(s.to_vec()),
537 DcsEnd => VTOwnedEvent::DcsEnd,
538 DcsCancel => VTOwnedEvent::DcsCancel,
539 OscStart => VTOwnedEvent::OscStart,
540 OscData(s) => VTOwnedEvent::OscData(s.to_vec()),
541 OscEnd { used_bel } => VTOwnedEvent::OscEnd {
542 used_bel: *used_bel,
543 },
544 OscCancel => VTOwnedEvent::OscCancel,
545 }
546 }
547}
548
549#[derive(Clone, PartialEq, Eq)]
550pub struct ParamBufOwned {
551 pub(crate) params: Params,
552}
553
554impl IntoIterator for ParamBufOwned {
555 type Item = Param;
556 type IntoIter = <Params as IntoIterator>::IntoIter;
557 fn into_iter(self) -> Self::IntoIter {
558 self.params.into_iter()
559 }
560}
561
562impl<'b> IntoIterator for &'b ParamBufOwned {
563 type Item = &'b [u8];
564 type IntoIter = Map<std::slice::Iter<'b, Param>, fn(&Param) -> &[u8]>;
565 fn into_iter(self) -> Self::IntoIter {
566 self.params.iter().map(|p| p.as_slice())
567 }
568}
569
570impl ParamBufOwned {
571 pub fn len(&self) -> usize {
572 self.params.len()
573 }
574
575 pub fn is_empty(&self) -> bool {
576 self.params.is_empty()
577 }
578
579 pub fn get(&self, index: usize) -> Option<&[u8]> {
580 self.params.get(index).map(|p| p.as_slice())
581 }
582
583 pub fn try_parse<T: std::str::FromStr>(&self, index: usize) -> Option<T> {
584 self.params.get(index).and_then(|p| {
585 std::str::from_utf8(p.as_slice())
586 .ok()
587 .and_then(|s| s.parse::<T>().ok())
588 })
589 }
590
591 pub fn borrow(&self) -> ParamBuf<'_> {
592 ParamBuf {
593 params: &self.params,
594 }
595 }
596}
597
598#[derive(Clone, PartialEq, Eq)]
599pub enum VTOwnedEvent {
600 Raw(Vec<u8>),
601 C0(u8),
602 Esc {
603 intermediates: VTIntermediate,
604 final_byte: u8,
605 },
606 Ss2 {
607 char: u8,
608 },
609 Ss3 {
610 char: u8,
611 },
612 Csi {
613 private: Option<u8>,
614 params: ParamBufOwned,
615 intermediates: VTIntermediate,
616 final_byte: u8,
617 },
618 DcsStart {
619 private: Option<u8>,
620 params: ParamBufOwned,
621 intermediates: VTIntermediate,
622 final_byte: u8,
623 },
624 DcsData(Vec<u8>),
625 DcsEnd,
626 DcsCancel,
627 OscStart,
628 OscData(Vec<u8>),
629 OscEnd {
630 used_bel: bool,
631 },
632 OscCancel,
633}
634
635impl std::fmt::Debug for VTOwnedEvent {
636 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
637 self.borrow().fmt(f)
638 }
639}
640
641impl VTOwnedEvent {
642 pub fn borrow(&self) -> VTEvent<'_> {
643 match self {
644 VTOwnedEvent::Raw(s) => VTEvent::Raw(s),
645 VTOwnedEvent::C0(b) => VTEvent::C0(*b),
646 VTOwnedEvent::Esc {
647 intermediates,
648 final_byte,
649 } => VTEvent::Esc {
650 intermediates: intermediates.clone(),
651 final_byte: *final_byte,
652 },
653 VTOwnedEvent::Ss2 { char } => VTEvent::Ss2 { char: *char },
654 VTOwnedEvent::Ss3 { char } => VTEvent::Ss3 { char: *char },
655 VTOwnedEvent::Csi {
656 private,
657 params,
658 intermediates,
659 final_byte,
660 } => VTEvent::Csi {
661 private: private.clone(),
662 params: params.borrow(),
663 intermediates: intermediates.clone(),
664 final_byte: *final_byte,
665 },
666 VTOwnedEvent::DcsStart {
667 private,
668 params,
669 intermediates,
670 final_byte,
671 } => VTEvent::DcsStart {
672 private: private.clone(),
673 params: params.borrow(),
674 intermediates: intermediates.clone(),
675 final_byte: *final_byte,
676 },
677 VTOwnedEvent::DcsData(s) => VTEvent::DcsData(s),
678 VTOwnedEvent::DcsEnd => VTEvent::DcsEnd,
679 VTOwnedEvent::DcsCancel => VTEvent::DcsCancel,
680 VTOwnedEvent::OscStart => VTEvent::OscStart,
681 VTOwnedEvent::OscData(s) => VTEvent::OscData(s),
682 VTOwnedEvent::OscEnd { used_bel } => VTEvent::OscEnd {
683 used_bel: *used_bel,
684 },
685 VTOwnedEvent::OscCancel => VTEvent::OscCancel,
686 }
687 }
688}
689
690pub struct CSI<'a> {
691 pub private: Option<u8>,
692 pub params: ParamBuf<'a>,
693 pub intermediates: VTIntermediate,
694 pub final_byte: u8,
695}