1use std::ops::Range;
2
3use smallvec::SmallVec;
4
5const ESC: u8 = 0x1B;
6const BEL: u8 = 0x07;
7const DEL: u8 = 0x7F;
8const CAN: u8 = 0x18;
9const SUB: u8 = 0x1A;
10const CSI: u8 = b'[';
11const OSC: u8 = b']';
12const SS3: u8 = b'O';
13const DCS: u8 = b'P';
14const ST_FINAL: u8 = b'\\';
15
16#[derive(Default, Clone, Copy, PartialEq, Eq)]
17pub struct VTIntermediate {
18 data: [u8; 2],
19}
20
21impl VTIntermediate {
22 pub const fn empty() -> Self {
23 Self { data: [0, 0] }
24 }
25
26 pub const fn one(c: u8) -> Self {
27 assert!(c >= 0x20 && c <= 0x2F);
28 Self { data: [c, 0] }
29 }
30
31 pub const fn two(c1: u8, c2: u8) -> Self {
32 assert!(c1 >= 0x20 && c1 <= 0x2F);
33 assert!(c2 >= 0x20 && c2 <= 0x2F);
34 Self { data: [c1, c2] }
35 }
36
37 pub fn has(&self, c: u8) -> bool {
38 self.data[0] == c || self.data[1] == c
39 }
40
41 pub fn clear(&mut self) {
42 self.data[0] = 0;
43 self.data[1] = 0;
44 }
45
46 pub fn is_empty(&self) -> bool {
47 self.data[0] == 0 && self.data[1] == 0
48 }
49
50 pub fn len(&self) -> usize {
51 self.data.iter().filter(|&&c| c != 0).count()
52 }
53
54 #[must_use]
55 pub fn push(&mut self, c: u8) -> bool {
56 if c < 0x20 || c > 0x2F {
57 return false;
58 }
59
60 if self.data[0] == 0 {
61 self.data[0] = c;
62 true
63 } else if self.data[1] == 0 {
64 self.data[1] = c;
65 true
66 } else {
67 false
68 }
69 }
70
71 const fn const_eq(&self, other: &Self) -> bool {
72 self.data[0] == other.data[0] && self.data[1] == other.data[1]
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 struct VTEscapeSignature {
93 pub prefix: u8,
94 pub private: Option<u8>,
95 pub intermediates: VTIntermediate,
96 pub final_byte: u8,
97 pub param_count: Range<u8>,
98}
99
100impl VTEscapeSignature {
101 pub const fn csi(
102 private: Option<u8>,
103 param_count: Range<u8>,
104 intermediates: VTIntermediate,
105 final_byte: u8,
106 ) -> Self {
107 Self {
108 prefix: CSI,
109 private,
110 intermediates,
111 final_byte,
112 param_count,
113 }
114 }
115
116 pub const fn ss3(intermediates: VTIntermediate, final_byte: u8) -> Self {
117 Self {
118 prefix: SS3,
119 private: None,
120 intermediates,
121 final_byte,
122 param_count: u8::MIN..u8::MAX,
123 }
124 }
125
126 pub const fn dcs(
127 priv_prefix: Option<u8>,
128 param_count: Range<u8>,
129 intermediates: VTIntermediate,
130 final_byte: u8,
131 ) -> Self {
132 Self {
133 prefix: DCS,
134 private: priv_prefix,
135 intermediates,
136 final_byte,
137 param_count,
138 }
139 }
140
141 pub const fn osc(intermediates: VTIntermediate, final_byte: u8) -> Self {
142 Self {
143 prefix: OSC,
144 private: None,
145 intermediates,
146 final_byte,
147 param_count: u8::MIN..u8::MAX,
148 }
149 }
150
151 pub fn matches(&self, entry: &VTEvent) -> bool {
152 match entry {
154 VTEvent::Esc {
155 intermediates,
156 final_byte,
157 } => self.final_byte == *final_byte && self.intermediates.const_eq(intermediates),
158 VTEvent::Csi {
159 private,
160 params,
161 intermediates,
162 final_byte,
163 } => {
164 self.prefix == CSI
165 && self.final_byte == *final_byte
166 && self.intermediates.const_eq(intermediates)
167 && self.const_private_eq(private)
168 && self.const_contains(params.len())
169 }
170 VTEvent::Ss3 {
171 intermediates,
172 final_byte,
173 } => {
174 self.prefix == SS3
175 && self.final_byte == *final_byte
176 && self.intermediates.const_eq(intermediates)
177 }
178 VTEvent::DcsStart {
179 priv_prefix,
180 params,
181 intermediates,
182 final_byte,
183 } => {
184 self.prefix == DCS
185 && self.final_byte == *final_byte
186 && self.intermediates.const_eq(intermediates)
187 && self.private == *priv_prefix
188 && self.const_contains(params.len())
189 }
190 _ => false,
191 }
192 }
193
194 const fn const_private_eq(&self, other: &Option<u8>) -> bool {
195 match (self.private, other) {
196 (Some(a), Some(b)) => a == *b,
197 (None, None) => true,
198 _ => false,
199 }
200 }
201
202 fn const_contains(&self, len: usize) -> bool {
203 self.param_count.contains(&(len as u8))
205 }
206}
207
208pub enum VTEvent<'a> {
209 Raw(&'a [u8]),
211
212 C0(u8),
214
215 Esc {
217 intermediates: VTIntermediate,
218 final_byte: u8,
219 },
220
221 Csi {
223 private: Option<u8>,
224 params: smallvec::SmallVec<[&'a [u8]; 4]>,
225 intermediates: VTIntermediate,
226 final_byte: u8,
227 },
228
229 Ss3 {
231 intermediates: VTIntermediate,
232 final_byte: u8,
233 },
234
235 DcsStart {
237 priv_prefix: Option<u8>,
238 params: smallvec::SmallVec<[&'a [u8]; 4]>,
239 intermediates: VTIntermediate,
240 final_byte: u8,
241 },
242 DcsData(&'a [u8]),
243 DcsEnd,
244
245 OscStart,
247 OscData(&'a [u8]),
248 OscEnd {
249 used_bel: bool,
250 },
251}
252
253impl<'a> std::fmt::Debug for VTEvent<'a> {
254 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
255 match self {
256 VTEvent::Raw(s) => {
257 write!(f, "Raw('")?;
258 for chunk in s.utf8_chunks() {
259 write!(f, "{}", chunk.valid())?;
260 if !chunk.invalid().is_empty() {
261 write!(f, "<{}>", hex::encode(chunk.invalid()))?;
262 }
263 }
264 write!(f, "')")?;
265 Ok(())
266 }
267 VTEvent::C0(b) => write!(f, "C0({:02x})", b),
268 VTEvent::Esc {
269 intermediates,
270 final_byte,
271 } => {
272 write!(f, "Esc({:?}", intermediates)?;
273 write!(f, ", {})", *final_byte as char)?;
274 Ok(())
275 }
276 VTEvent::Csi {
277 private,
278 params,
279 intermediates,
280 final_byte,
281 } => {
282 write!(f, "Csi(")?;
283 if let Some(p) = private {
284 write!(f, "{:?}", *p as char)?;
285 }
286 for param in params {
287 write!(f, ", '")?;
288 for chunk in param.utf8_chunks() {
289 write!(f, "{}", chunk.valid())?;
290 if !chunk.invalid().is_empty() {
291 write!(f, "<{}>", hex::encode(chunk.invalid()))?;
292 }
293 }
294 write!(f, "'")?;
295 }
296 write!(f, ", {:?}", intermediates)?;
297 write!(f, ", {:?})", *final_byte as char)?;
298 Ok(())
299 }
300 VTEvent::Ss3 {
301 intermediates,
302 final_byte,
303 } => {
304 write!(f, "Ss3(")?;
305 write!(f, "{:?}", intermediates)?;
306 write!(f, ", {})", *final_byte as char)?;
307 Ok(())
308 }
309 VTEvent::DcsStart {
310 priv_prefix,
311 params,
312 intermediates,
313 final_byte,
314 } => {
315 write!(f, "DcsStart(")?;
316 if let Some(p) = priv_prefix {
317 write!(f, "{:?}", *p as char)?;
318 }
319 for param in params {
320 write!(f, ", {:02x?}", param)?;
321 }
322 write!(f, ", {:?}", intermediates)?;
323 write!(f, ", {})", *final_byte as char)?;
324 Ok(())
325 }
326 VTEvent::DcsData(s) => {
327 write!(f, "DcsData('")?;
328 for chunk in s.utf8_chunks() {
329 write!(f, "{}", chunk.valid())?;
330 if !chunk.invalid().is_empty() {
331 write!(f, "<{}>", hex::encode(chunk.invalid()))?;
332 }
333 }
334 write!(f, "')")?;
335 Ok(())
336 }
337 VTEvent::DcsEnd => write!(f, "DcsEnd"),
338 VTEvent::OscStart => write!(f, "OscStart"),
339 VTEvent::OscData(s) => {
340 write!(f, "OscData('")?;
341 for chunk in s.utf8_chunks() {
342 write!(f, "{}", chunk.valid())?;
343 if !chunk.invalid().is_empty() {
344 write!(f, "<{}>", hex::encode(chunk.invalid()))?;
345 }
346 }
347 write!(f, "')")?;
348 Ok(())
349 }
350 VTEvent::OscEnd { .. } => {
351 write!(f, "OscEnd")?;
352 Ok(())
353 }
354 }
355 }
356}
357
358#[inline]
359fn is_c0(b: u8) -> bool {
360 b <= 0x1F
361}
362#[inline]
363fn is_printable(b: u8) -> bool {
364 (0x20..=0x7E).contains(&b)
365}
366#[inline]
367fn is_intermediate(b: u8) -> bool {
368 (0x20..=0x2F).contains(&b)
369}
370#[inline]
371fn is_final(b: u8) -> bool {
372 (0x30..=0x7E).contains(&b)
373}
374#[inline]
375fn is_digit(b: u8) -> bool {
376 (b'0'..=b'9').contains(&b)
377}
378#[inline]
379fn is_priv(b: u8) -> bool {
380 matches!(b, b'<' | b'=' | b'>' | b'?')
381}
382
383#[derive(Debug, Copy, Clone, PartialEq, Eq)]
384enum State {
385 Ground,
386 Escape,
387 EscInt,
388 CsiEntry,
389 CsiParam,
390 CsiInt,
391 CsiIgnore,
392 DcsEntry,
393 DcsParam,
394 DcsInt,
395 DcsIgnore,
396 DcsPassthrough,
397 DcsEsc,
398 OscString,
399 OscEsc,
400 SosPmApcString,
401 SpaEsc,
402}
403
404pub struct VTPushParser {
405 st: State,
406
407 raw_buf: Vec<u8>,
409
410 ints: VTIntermediate,
412 params: Vec<Vec<u8>>,
413 cur_param: Vec<u8>,
414 priv_prefix: Option<u8>,
415
416 stream_buf: Vec<u8>,
418 used_bel: bool,
419
420 max_short_hdr: usize,
422 stream_flush: usize,
423}
424
425impl VTPushParser {
426 pub fn new() -> Self {
427 Self {
428 st: State::Ground,
429 raw_buf: Vec::with_capacity(256),
430 ints: VTIntermediate::default(),
431 params: Vec::with_capacity(8),
432 cur_param: Vec::with_capacity(8),
433 priv_prefix: None,
434 stream_buf: Vec::with_capacity(8192),
435 used_bel: false,
436 max_short_hdr: 4096,
437 stream_flush: 8192,
438 }
439 }
440
441 pub fn with_limits(mut self, max_short_hdr: usize, stream_flush: usize) -> Self {
442 self.max_short_hdr = max_short_hdr;
443 self.stream_flush = stream_flush.max(1);
444 self
445 }
446
447 pub fn feed_with<F: FnMut(VTEvent)>(&mut self, input: &[u8], mut cb: F) {
452 for &b in input {
453 self.push_with(b, &mut cb);
454 }
455 self.flush_raw_if_any(&mut cb);
457 }
458
459 pub fn push_with<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
460 use State::*;
461 match self.st {
462 Ground => self.on_ground(b, cb),
463 Escape => self.on_escape(b, cb),
464 EscInt => self.on_esc_int(b, cb),
465
466 CsiEntry => self.on_csi_entry(b, cb),
467 CsiParam => self.on_csi_param(b, cb),
468 CsiInt => self.on_csi_int(b, cb),
469 CsiIgnore => self.on_csi_ignore(b, cb),
470
471 DcsEntry => self.on_dcs_entry(b, cb),
472 DcsParam => self.on_dcs_param(b, cb),
473 DcsInt => self.on_dcs_int(b, cb),
474 DcsIgnore => self.on_dcs_ignore(b, cb),
475 DcsPassthrough => self.on_dcs_pass(b, cb),
476 DcsEsc => self.on_dcs_esc(b, cb),
477
478 OscString => self.on_osc_string(b, cb),
479 OscEsc => self.on_osc_esc(b, cb),
480
481 SosPmApcString => self.on_spa_string(b, cb),
482 SpaEsc => self.on_spa_esc(b, cb),
483 }
484 }
485
486 pub fn finish<F: FnMut(VTEvent)>(&mut self, cb: &mut F) {
487 self.reset_collectors();
489 self.st = State::Ground;
490 self.flush_raw_if_any(cb);
491 }
492
493 fn flush_raw_if_any<F: FnMut(VTEvent)>(&mut self, cb: &mut F) {
498 if !self.raw_buf.is_empty() {
499 let slice = &self.raw_buf[..];
500 cb(VTEvent::Raw(slice));
501 self.raw_buf.clear(); }
503 }
504
505 fn clear_hdr_collectors(&mut self) {
506 self.ints.clear();
507 self.params.clear();
508 self.cur_param.clear();
509 self.priv_prefix = None;
510 }
511
512 fn reset_collectors(&mut self) {
513 self.clear_hdr_collectors();
514 self.stream_buf.clear();
515 self.used_bel = false;
516 }
517
518 fn next_param(&mut self) {
519 self.params.push(std::mem::take(&mut self.cur_param));
520 }
521
522 fn finish_params_if_any(&mut self) {
523 if !self.cur_param.is_empty() || !self.params.is_empty() {
524 self.next_param();
525 }
526 }
527
528 fn emit_esc<F: FnMut(VTEvent)>(&mut self, final_byte: u8, cb: &mut F) {
529 self.flush_raw_if_any(cb);
530 cb(VTEvent::Esc {
531 intermediates: self.ints,
532 final_byte,
533 });
534 self.clear_hdr_collectors();
535 }
536
537 fn emit_csi<F: FnMut(VTEvent)>(&mut self, final_byte: u8, cb: &mut F) {
538 self.flush_raw_if_any(cb);
539 self.finish_params_if_any();
540
541 let mut borrowed: SmallVec<[&[u8]; 4]> = SmallVec::new();
543 borrowed.extend(self.params.iter().map(|v| v.as_slice()));
544
545 let privp = self.priv_prefix.take();
546 cb(VTEvent::Csi {
547 private: privp,
548 params: borrowed,
549 intermediates: self.ints,
550 final_byte,
551 });
552 self.clear_hdr_collectors();
553 }
554
555 fn dcs_start<F: FnMut(VTEvent)>(&mut self, final_byte: u8, cb: &mut F) {
556 self.flush_raw_if_any(cb);
557 self.finish_params_if_any();
558
559 let mut borrowed: SmallVec<[&[u8]; 4]> = SmallVec::new();
560 borrowed.extend(self.params.iter().map(|v| v.as_slice()));
561
562 let privp = self.priv_prefix.take();
563 cb(VTEvent::DcsStart {
564 priv_prefix: privp,
565 params: borrowed,
566 intermediates: self.ints,
567 final_byte,
568 });
569 self.stream_buf.clear();
570 self.clear_hdr_collectors();
572 }
573
574 fn dcs_put<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
575 self.stream_buf.push(b);
576 if self.stream_buf.len() >= self.stream_flush {
577 let slice = &self.stream_buf[..];
578 cb(VTEvent::DcsData(slice));
579 self.stream_buf.clear();
580 }
581 }
582
583 fn dcs_end<F: FnMut(VTEvent)>(&mut self, cb: &mut F) {
584 if !self.stream_buf.is_empty() {
585 let slice = &self.stream_buf[..];
586 cb(VTEvent::DcsData(slice));
587 self.stream_buf.clear();
588 }
589 cb(VTEvent::DcsEnd);
590 self.reset_collectors();
591 }
592
593 fn osc_start<F: FnMut(VTEvent)>(&mut self, cb: &mut F) {
594 self.flush_raw_if_any(cb);
595 self.used_bel = false;
596 self.stream_buf.clear();
597 cb(VTEvent::OscStart);
598 }
599
600 fn osc_put<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
601 self.stream_buf.push(b);
602 if self.stream_buf.len() >= self.stream_flush {
603 let slice = &self.stream_buf[..];
604 cb(VTEvent::OscData(slice));
605 self.stream_buf.clear();
606 }
607 }
608
609 fn osc_end<F: FnMut(VTEvent)>(&mut self, cb: &mut F) {
610 if !self.stream_buf.is_empty() {
611 let slice = &self.stream_buf[..];
612 cb(VTEvent::OscData(slice));
613 self.stream_buf.clear();
614 }
615 let used_bel = self.used_bel;
616 cb(VTEvent::OscEnd { used_bel });
617 self.reset_collectors();
618 }
619
620 fn on_ground<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
625 match b {
626 ESC => {
627 self.clear_hdr_collectors();
628 self.flush_raw_if_any(cb);
629 self.st = State::Escape;
630 }
631 DEL => {}
632 c if is_c0(c) => {
633 self.flush_raw_if_any(cb);
634 cb(VTEvent::C0(c));
635 }
636 p if is_printable(p) => {
637 self.raw_buf.push(p);
638 }
639 _ => {
640 self.raw_buf.push(b);
641 } }
643 }
644
645 fn on_escape<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
646 use State::*;
647 match b {
648 CAN | SUB => {
649 self.st = Ground;
650 }
651 DEL => {}
652 c if is_intermediate(c) => {
653 self.ints.push(c);
654 self.st = EscInt;
655 }
656 CSI => {
657 self.clear_hdr_collectors();
658 self.st = CsiEntry;
659 }
660 DCS => {
661 self.clear_hdr_collectors();
662 self.st = DcsEntry;
663 }
664 OSC => {
665 self.clear_hdr_collectors();
666 self.osc_start(cb);
667 self.st = OscString;
668 }
669 b'X' | b'^' | b'_' => {
670 self.clear_hdr_collectors();
671 self.st = State::SosPmApcString;
672 }
673 c if is_final(c) => {
674 self.emit_esc(c, cb);
675 self.st = Ground;
676 }
677 ESC => { }
678 _ => {
679 self.st = Ground;
680 }
681 }
682 }
683 fn on_esc_int<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
684 use State::*;
685 match b {
686 CAN | SUB => {
687 self.st = Ground;
688 }
689 DEL => {}
690 c if is_intermediate(c) => {
691 self.ints.push(c);
692 }
693 c if is_final(c) => {
694 self.emit_esc(c, cb);
695 self.st = Ground;
696 }
697 _ => {
698 self.st = Ground;
699 }
700 }
701 }
702
703 fn on_csi_entry<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
705 use State::*;
706 match b {
707 CAN | SUB => {
708 self.st = Ground;
709 }
710 DEL => {}
711 ESC => {
712 self.st = Escape;
713 }
714 c if is_priv(c) => {
715 self.priv_prefix = Some(c);
716 self.st = CsiParam;
717 }
718 d if is_digit(d) => {
719 self.cur_param.push(d);
720 self.st = CsiParam;
721 }
722 b';' => {
723 self.next_param();
724 self.st = CsiParam;
725 }
726 b':' => {
727 self.cur_param.push(b':');
728 self.st = CsiParam;
729 }
730 c if is_intermediate(c) => {
731 self.ints.push(c);
732 self.st = CsiInt;
733 }
734 c if is_final(c) => {
735 self.emit_csi(c, cb);
736 self.st = Ground;
737 }
738 _ => {
739 self.st = CsiIgnore;
740 }
741 }
742 }
743 fn on_csi_param<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
744 use State::*;
745 match b {
746 CAN | SUB => {
747 self.st = Ground;
748 }
749 DEL => {}
750 ESC => {
751 self.st = Escape;
752 }
753 d if is_digit(d) => {
754 self.cur_param.push(d);
755 }
756 b';' => {
757 self.next_param();
758 }
759 b':' => {
760 self.cur_param.push(b':');
761 }
762 c if is_intermediate(c) => {
763 self.ints.push(c);
764 self.st = CsiInt;
765 }
766 c if is_final(c) => {
767 self.emit_csi(c, cb);
768 self.st = Ground;
769 }
770 _ => {
771 self.st = CsiIgnore;
772 }
773 }
774 }
775 fn on_csi_int<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
776 use State::*;
777 match b {
778 CAN | SUB => {
779 self.st = Ground;
780 }
781 DEL => {}
782 ESC => {
783 self.st = Escape;
784 }
785 c if is_intermediate(c) => {
786 self.ints.push(c);
787 }
788 c if is_final(c) => {
789 self.emit_csi(c, cb);
790 self.st = Ground;
791 }
792 _ => {
793 self.st = CsiIgnore;
794 }
795 }
796 }
797 fn on_csi_ignore<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
798 use State::*;
799 match b {
800 CAN | SUB => {
801 self.st = Ground;
802 }
803 DEL => {}
804 ESC => {
805 self.st = Escape;
806 }
807 c if is_final(c) => {
808 self.st = Ground;
809 }
810 _ => {}
811 }
812 }
813
814 fn on_dcs_entry<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
816 use State::*;
817 match b {
818 CAN | SUB => {
819 self.st = Ground;
820 }
821 DEL => {}
822 ESC => {
823 self.st = Escape;
824 }
825 c if is_priv(c) => {
826 self.priv_prefix = Some(c);
827 self.st = DcsParam;
828 }
829 d if is_digit(d) => {
830 self.cur_param.push(d);
831 self.st = DcsParam;
832 }
833 b';' => {
834 self.next_param();
835 self.st = DcsParam;
836 }
837 b':' => {
838 self.st = DcsIgnore;
839 }
840 c if is_intermediate(c) => {
841 self.ints.push(c);
842 self.st = DcsInt;
843 }
844 c if is_final(c) => {
845 self.dcs_start(c, cb);
846 self.st = DcsPassthrough;
847 }
848 _ => {
849 self.st = DcsIgnore;
850 }
851 }
852 }
853 fn on_dcs_param<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
854 use State::*;
855 match b {
856 CAN | SUB => {
857 self.st = Ground;
858 }
859 DEL => {}
860 ESC => {
861 self.st = Escape;
862 }
863 d if is_digit(d) => {
864 self.cur_param.push(d);
865 }
866 b';' => {
867 self.next_param();
868 }
869 b':' => {
870 self.st = DcsIgnore;
871 }
872 c if is_intermediate(c) => {
873 self.ints.push(c);
874 self.st = DcsInt;
875 }
876 c if is_final(c) => {
877 self.dcs_start(c, cb);
878 self.st = DcsPassthrough;
879 }
880 _ => {
881 self.st = DcsIgnore;
882 }
883 }
884 }
885 fn on_dcs_int<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
886 use State::*;
887 match b {
888 CAN | SUB => {
889 self.st = Ground;
890 }
891 DEL => {}
892 ESC => {
893 self.st = Escape;
894 }
895 c if is_intermediate(c) => {
896 self.ints.push(c);
897 }
898 c if is_final(c) => {
899 self.dcs_start(c, cb);
900 self.st = DcsPassthrough;
901 }
902 _ => {
903 self.st = DcsIgnore;
904 }
905 }
906 }
907 fn on_dcs_ignore<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
908 use State::*;
909 match b {
910 CAN | SUB => {
911 self.st = Ground;
912 }
913 DEL => {}
914 ESC => {
915 self.st = Escape;
916 }
917 _ => {}
919 }
920 }
921 fn on_dcs_pass<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
922 use State::*;
923 match b {
924 CAN | SUB => {
925 self.dcs_end(cb);
926 self.st = Ground;
927 }
928 DEL => {}
929 ESC => {
930 self.st = DcsEsc;
931 }
932 _ => {
933 self.dcs_put(b, cb);
934 }
935 }
936 }
937 fn on_dcs_esc<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
938 use State::*;
939 match b {
940 ST_FINAL => {
941 self.dcs_end(cb);
942 self.st = Ground;
943 } ESC => {
945 self.dcs_put(ESC, cb); }
947 _ => {
948 self.dcs_put(ESC, cb);
949 self.dcs_put(b, cb);
950 self.st = DcsPassthrough;
951 }
952 }
953 }
954
955 fn on_osc_string<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
957 use State::*;
958 match b {
959 CAN | SUB => {
960 self.reset_collectors();
961 self.st = Ground;
962 }
963 DEL => {}
964 BEL => {
965 self.used_bel = true;
966 self.osc_end(cb);
967 self.st = Ground;
968 }
969 ESC => {
970 self.st = State::OscEsc;
971 }
972 p if is_printable(p) => {
973 self.osc_put(p, cb);
974 }
975 _ => {} }
977 }
978 fn on_osc_esc<F: FnMut(VTEvent)>(&mut self, b: u8, cb: &mut F) {
979 use State::*;
980 match b {
981 ST_FINAL => {
982 self.used_bel = false;
983 self.osc_end(cb);
984 self.st = Ground;
985 } ESC => {
987 self.osc_put(ESC, cb); }
989 _ => {
990 self.osc_put(ESC, cb);
991 self.osc_put(b, cb);
992 self.st = OscString;
993 }
994 }
995 }
996
997 fn on_spa_string<F: FnMut(VTEvent)>(&mut self, b: u8, _cb: &mut F) {
999 match b {
1000 CAN | SUB => {
1001 self.reset_collectors();
1002 self.st = State::Ground;
1003 }
1004 DEL => {}
1005 ESC => {
1006 self.st = State::SpaEsc;
1007 }
1008 _ => {}
1009 }
1010 }
1011 fn on_spa_esc<F: FnMut(VTEvent)>(&mut self, b: u8, _cb: &mut F) {
1012 match b {
1013 ST_FINAL => {
1014 self.reset_collectors();
1015 self.st = State::Ground;
1016 }
1017 ESC => { }
1018 _ => {
1019 self.st = State::SosPmApcString;
1020 }
1021 }
1022 }
1023}
1024
1025#[cfg(test)]
1026mod tests {
1027 use pretty_assertions::assert_eq;
1028
1029 use super::*;
1030
1031 fn decode_stream(input: &[u8]) -> String {
1032 println!("Input:");
1033 let mut s = Vec::new();
1034 _ = hxdmp::hexdump(input, &mut s);
1035 println!("{}", String::from_utf8_lossy(&s));
1036 let mut parser = VTPushParser::new();
1037 let mut result = String::new();
1038 let mut callback = |vt_input: VTEvent<'_>| {
1039 result.push_str(&format!("{:?}\n", vt_input));
1040 };
1041 parser.feed_with(input, &mut callback);
1042 println!("Result:");
1043 println!("{}", result);
1044 result
1045 }
1046
1047 #[test]
1048 fn test_large_escape2() {
1049 let result = decode_stream(
1050 &hex::decode(
1051 r#"
1052 1b5b495445524d3220332e352e31346e1b5d31303b7267623a646361612f6
1053 46361622f646361611b5c1b5d31313b7267623a313538652f313933612f31
1054 6537351b5c1b5b3f36343b313b323b343b363b31373b31383b32313b32326
1055 31b5b3e36343b323530303b30631b50217c36393534373236441b5c1b503e
1056 7c695465726d3220332e352e31341b5c1b5b383b33343b31343874"#
1057 .replace(char::is_whitespace, ""),
1058 )
1059 .unwrap(),
1060 );
1061 assert_eq!(
1062 result.trim(),
1063 r#"
1064Csi(, '', 'I')
1065Raw('TERM2 3.5.14n')
1066OscStart
1067OscData('10;rgb:dcaa/dcab/dcaa')
1068OscEnd
1069OscStart
1070OscData('11;rgb:158e/193a/1e75')
1071OscEnd
1072Csi('?', '64', '1', '2', '4', '6', '17', '18', '21', '22', '', 'c')
1073Csi('>', '64', '2500', '0', '', 'c')
1074DcsStart(, '!', |)
1075DcsData('6954726D')
1076DcsEnd
1077DcsStart('>', '', |)
1078DcsData('iTerm2 3.5.14')
1079DcsEnd
1080Csi(, '8', '34', '148', '', 't')
1081 "#
1082 .trim()
1083 );
1084 }
1085}