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