1#![deny(clippy::all, clippy::if_not_else, clippy::enum_glob_use)]
34#![cfg_attr(all(feature = "nightly", test), feature(test))]
35#![cfg_attr(feature = "no_std", no_std)]
36
37use core::mem::MaybeUninit;
38
39#[cfg(feature = "no_std")]
40use arrayvec::ArrayVec;
41use utf8parse as utf8;
42
43mod definitions;
44mod params;
45mod table;
46
47#[cfg(feature = "ansi")]
48pub mod ansi;
49pub use params::{Params, ParamsIter};
50
51use definitions::{unpack, Action, State};
52
53const MAX_INTERMEDIATES: usize = 2;
54const MAX_OSC_PARAMS: usize = 16;
55#[cfg(any(feature = "no_std", test))]
56const MAX_OSC_RAW: usize = 1024;
57
58struct VtUtf8Receiver<'a, P: Perform>(&'a mut P, &'a mut State);
59
60impl<'a, P: Perform> utf8::Receiver for VtUtf8Receiver<'a, P> {
61 fn codepoint(&mut self, c: char) {
62 self.0.print(c);
63 *self.1 = State::Ground;
64 }
65
66 fn invalid_sequence(&mut self) {
67 self.0.print('�');
68 *self.1 = State::Ground;
69 }
70}
71
72#[derive(Default)]
76pub struct Parser {
77 state: State,
78 intermediates: [u8; MAX_INTERMEDIATES],
79 intermediate_idx: usize,
80 params: Params,
81 param: u16,
82 #[cfg(feature = "no_std")]
83 osc_raw: ArrayVec<u8, MAX_OSC_RAW>,
84 #[cfg(not(feature = "no_std"))]
85 osc_raw: Vec<u8>,
86 osc_params: [(usize, usize); MAX_OSC_PARAMS],
87 osc_num_params: usize,
88 ignoring: bool,
89 utf8_parser: utf8::Parser,
90}
91
92impl Parser {
93 pub fn new() -> Parser {
95 Parser::default()
96 }
97
98 #[inline]
99 fn params(&self) -> &Params {
100 &self.params
101 }
102
103 #[inline]
104 fn intermediates(&self) -> &[u8] {
105 &self.intermediates[..self.intermediate_idx]
106 }
107
108 #[inline]
114 pub fn advance<P: Perform>(&mut self, performer: &mut P, byte: u8) {
115 if let State::Utf8 = self.state {
117 self.process_utf8(performer, byte);
118 return;
119 }
120
121 let mut change = table::STATE_CHANGES[State::Anywhere as usize][byte as usize];
124
125 if change == 0 {
126 change = table::STATE_CHANGES[self.state as usize][byte as usize];
127 }
128
129 let (state, action) = unpack(change);
131
132 self.perform_state_change(performer, state, action, byte);
133 }
134
135 #[inline]
136 fn process_utf8<P>(&mut self, performer: &mut P, byte: u8)
137 where
138 P: Perform,
139 {
140 let mut receiver = VtUtf8Receiver(performer, &mut self.state);
141 let utf8_parser = &mut self.utf8_parser;
142 utf8_parser.advance(&mut receiver, byte);
143 }
144
145 #[inline]
146 fn perform_state_change<P>(&mut self, performer: &mut P, state: State, action: Action, byte: u8)
147 where
148 P: Perform,
149 {
150 macro_rules! maybe_action {
151 ($action:expr, $arg:expr) => {
152 match $action {
153 Action::None => (),
154 action => {
155 self.perform_action(performer, action, $arg);
156 },
157 }
158 };
159 }
160
161 match state {
162 State::Anywhere => {
163 self.perform_action(performer, action, byte);
165 },
166 state => {
167 match self.state {
168 State::DcsPassthrough => {
169 self.perform_action(performer, Action::Unhook, byte);
170 },
171 State::OscString => {
172 self.perform_action(performer, Action::OscEnd, byte);
173 },
174 _ => (),
175 }
176
177 maybe_action!(action, byte);
178
179 match state {
180 State::CsiEntry | State::DcsEntry | State::Escape => {
181 self.perform_action(performer, Action::Clear, byte);
182 },
183 State::DcsPassthrough => {
184 self.perform_action(performer, Action::Hook, byte);
185 },
186 State::OscString => {
187 self.perform_action(performer, Action::OscStart, byte);
188 },
189 _ => (),
190 }
191
192 self.state = state;
194 },
195 }
196 }
197
198 #[inline]
202 fn osc_dispatch<P: Perform>(&self, performer: &mut P, byte: u8) {
203 let mut slices: [MaybeUninit<&[u8]>; MAX_OSC_PARAMS] =
204 unsafe { MaybeUninit::uninit().assume_init() };
205
206 for (i, slice) in slices.iter_mut().enumerate().take(self.osc_num_params) {
207 let indices = self.osc_params[i];
208 *slice = MaybeUninit::new(&self.osc_raw[indices.0..indices.1]);
209 }
210
211 unsafe {
212 let num_params = self.osc_num_params;
213 let params = &slices[..num_params] as *const [MaybeUninit<&[u8]>] as *const [&[u8]];
214 performer.osc_dispatch(&*params, byte == 0x07);
215 }
216 }
217
218 #[inline]
219 fn perform_action<P: Perform>(&mut self, performer: &mut P, action: Action, byte: u8) {
220 match action {
221 Action::Print => performer.print(byte as char),
222 Action::Execute => performer.execute(byte),
223 Action::Hook => {
224 if self.params.is_full() {
225 self.ignoring = true;
226 } else {
227 self.params.push(self.param);
228 }
229
230 performer.hook(self.params(), self.intermediates(), self.ignoring, byte as char);
231 },
232 Action::Put => performer.put(byte),
233 Action::OscStart => {
234 self.osc_raw.clear();
235 self.osc_num_params = 0;
236 },
237 Action::OscPut => {
238 #[cfg(feature = "no_std")]
239 {
240 if self.osc_raw.is_full() {
241 return;
242 }
243 }
244
245 let idx = self.osc_raw.len();
246
247 if byte == b';' {
249 let param_idx = self.osc_num_params;
250 match param_idx {
251 MAX_OSC_PARAMS => return,
253
254 0 => {
256 self.osc_params[param_idx] = (0, idx);
257 },
258
259 _ => {
261 let prev = self.osc_params[param_idx - 1];
262 let begin = prev.1;
263 self.osc_params[param_idx] = (begin, idx);
264 },
265 }
266
267 self.osc_num_params += 1;
268 } else {
269 self.osc_raw.push(byte);
270 }
271 },
272 Action::OscEnd => {
273 let param_idx = self.osc_num_params;
274 let idx = self.osc_raw.len();
275
276 match param_idx {
277 MAX_OSC_PARAMS => (),
279
280 0 => {
282 self.osc_params[param_idx] = (0, idx);
283 self.osc_num_params += 1;
284 },
285
286 _ => {
288 let prev = self.osc_params[param_idx - 1];
289 let begin = prev.1;
290 self.osc_params[param_idx] = (begin, idx);
291 self.osc_num_params += 1;
292 },
293 }
294 self.osc_dispatch(performer, byte);
295 },
296 Action::Unhook => performer.unhook(),
297 Action::CsiDispatch => {
298 if self.params.is_full() {
299 self.ignoring = true;
300 } else {
301 self.params.push(self.param);
302 }
303
304 performer.csi_dispatch(
305 self.params(),
306 self.intermediates(),
307 self.ignoring,
308 byte as char,
309 );
310 },
311 Action::EscDispatch => {
312 performer.esc_dispatch(self.intermediates(), self.ignoring, byte);
313 },
314 Action::Collect => {
315 if self.intermediate_idx == MAX_INTERMEDIATES {
316 self.ignoring = true;
317 } else {
318 self.intermediates[self.intermediate_idx] = byte;
319 self.intermediate_idx += 1;
320 }
321 },
322 Action::Param => {
323 if self.params.is_full() {
324 self.ignoring = true;
325 return;
326 }
327
328 if byte == b';' {
329 self.params.push(self.param);
330 self.param = 0;
331 } else if byte == b':' {
332 self.params.extend(self.param);
333 self.param = 0;
334 } else {
335 self.param = self.param.saturating_mul(10);
337 self.param = self.param.saturating_add((byte - b'0') as u16);
338 }
339 },
340 Action::Clear => {
341 self.intermediate_idx = 0;
343 self.ignoring = false;
344 self.param = 0;
345
346 self.params.clear();
347 },
348 Action::BeginUtf8 => self.process_utf8(performer, byte),
349 Action::Ignore => (),
350 Action::None => (),
351 }
352 }
353}
354
355pub trait Perform {
366 fn print(&mut self, _c: char) {}
368
369 fn execute(&mut self, _byte: u8) {}
371
372 fn hook(&mut self, _params: &Params, _intermediates: &[u8], _ignore: bool, _action: char) {}
382
383 fn put(&mut self, _byte: u8) {}
386
387 fn unhook(&mut self) {}
392
393 fn osc_dispatch(&mut self, _params: &[&[u8]], _bell_terminated: bool) {}
395
396 fn csi_dispatch(
402 &mut self,
403 _params: &Params,
404 _intermediates: &[u8],
405 _ignore: bool,
406 _action: char,
407 ) {
408 }
409
410 fn esc_dispatch(&mut self, _intermediates: &[u8], _ignore: bool, _byte: u8) {}
415}
416
417#[cfg(all(test, feature = "no_std"))]
418#[macro_use]
419extern crate std;
420
421#[cfg(test)]
422mod tests {
423 use super::*;
424
425 use std::vec::Vec;
426
427 static OSC_BYTES: &[u8] = &[
428 0x1b, 0x5d, b'2', b';', b'j', b'w', b'i', b'l', b'm', b'@', b'j', b'w', b'i', b'l', b'm', b'-', b'd',
430 b'e', b's', b'k', b':', b' ', b'~', b'/', b'c', b'o', b'd', b'e', b'/', b'a', b'l', b'a',
431 b'c', b'r', b'i', b't', b't', b'y', 0x07, ];
433
434 #[derive(Default)]
435 struct Dispatcher {
436 dispatched: Vec<Sequence>,
437 }
438
439 #[derive(Debug, PartialEq, Eq)]
440 enum Sequence {
441 Osc(Vec<Vec<u8>>, bool),
442 Csi(Vec<Vec<u16>>, Vec<u8>, bool, char),
443 Esc(Vec<u8>, bool, u8),
444 DcsHook(Vec<Vec<u16>>, Vec<u8>, bool, char),
445 DcsPut(u8),
446 DcsUnhook,
447 }
448
449 impl Perform for Dispatcher {
450 fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) {
451 let params = params.iter().map(|p| p.to_vec()).collect();
452 self.dispatched.push(Sequence::Osc(params, bell_terminated));
453 }
454
455 fn csi_dispatch(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: char) {
456 let params = params.iter().map(|subparam| subparam.to_vec()).collect();
457 let intermediates = intermediates.to_vec();
458 self.dispatched.push(Sequence::Csi(params, intermediates, ignore, c));
459 }
460
461 fn esc_dispatch(&mut self, intermediates: &[u8], ignore: bool, byte: u8) {
462 let intermediates = intermediates.to_vec();
463 self.dispatched.push(Sequence::Esc(intermediates, ignore, byte));
464 }
465
466 fn hook(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: char) {
467 let params = params.iter().map(|subparam| subparam.to_vec()).collect();
468 let intermediates = intermediates.to_vec();
469 self.dispatched.push(Sequence::DcsHook(params, intermediates, ignore, c));
470 }
471
472 fn put(&mut self, byte: u8) {
473 self.dispatched.push(Sequence::DcsPut(byte));
474 }
475
476 fn unhook(&mut self) {
477 self.dispatched.push(Sequence::DcsUnhook);
478 }
479 }
480
481 #[test]
482 fn parse_osc() {
483 let mut dispatcher = Dispatcher::default();
484 let mut parser = Parser::new();
485
486 for byte in OSC_BYTES {
487 parser.advance(&mut dispatcher, *byte);
488 }
489
490 assert_eq!(dispatcher.dispatched.len(), 1);
491 match &dispatcher.dispatched[0] {
492 Sequence::Osc(params, _) => {
493 assert_eq!(params.len(), 2);
494 assert_eq!(params[0], &OSC_BYTES[2..3]);
495 assert_eq!(params[1], &OSC_BYTES[4..(OSC_BYTES.len() - 1)]);
496 },
497 _ => panic!("expected osc sequence"),
498 }
499 }
500
501 #[test]
502 fn parse_empty_osc() {
503 let mut dispatcher = Dispatcher::default();
504 let mut parser = Parser::new();
505
506 for byte in &[0x1b, 0x5d, 0x07] {
507 parser.advance(&mut dispatcher, *byte);
508 }
509
510 assert_eq!(dispatcher.dispatched.len(), 1);
511 match &dispatcher.dispatched[0] {
512 Sequence::Osc(..) => (),
513 _ => panic!("expected osc sequence"),
514 }
515 }
516
517 #[test]
518 fn parse_osc_max_params() {
519 let params = ";".repeat(params::MAX_PARAMS + 1);
520 let input = format!("\x1b]{}\x1b", ¶ms[..]).into_bytes();
521 let mut dispatcher = Dispatcher::default();
522 let mut parser = Parser::new();
523
524 for byte in input {
525 parser.advance(&mut dispatcher, byte);
526 }
527
528 assert_eq!(dispatcher.dispatched.len(), 1);
529 match &dispatcher.dispatched[0] {
530 Sequence::Osc(params, _) => {
531 assert_eq!(params.len(), MAX_OSC_PARAMS);
532 assert!(params.iter().all(Vec::is_empty));
533 },
534 _ => panic!("expected osc sequence"),
535 }
536 }
537
538 #[test]
539 fn osc_bell_terminated() {
540 static INPUT: &[u8] = b"\x1b]11;ff/00/ff\x07";
541 let mut dispatcher = Dispatcher::default();
542 let mut parser = Parser::new();
543
544 for byte in INPUT {
545 parser.advance(&mut dispatcher, *byte);
546 }
547
548 assert_eq!(dispatcher.dispatched.len(), 1);
549 match &dispatcher.dispatched[0] {
550 Sequence::Osc(_, true) => (),
551 _ => panic!("expected osc with bell terminator"),
552 }
553 }
554
555 #[test]
556 fn osc_c0_st_terminated() {
557 static INPUT: &[u8] = b"\x1b]11;ff/00/ff\x1b\\";
558 let mut dispatcher = Dispatcher::default();
559 let mut parser = Parser::new();
560
561 for byte in INPUT {
562 parser.advance(&mut dispatcher, *byte);
563 }
564
565 assert_eq!(dispatcher.dispatched.len(), 2);
566 match &dispatcher.dispatched[0] {
567 Sequence::Osc(_, false) => (),
568 _ => panic!("expected osc with ST terminator"),
569 }
570 }
571
572 #[test]
573 fn parse_osc_with_utf8_arguments() {
574 static INPUT: &[u8] = &[
575 0x0d, 0x1b, 0x5d, 0x32, 0x3b, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x27, 0xc2, 0xaf, 0x5c,
576 0x5f, 0x28, 0xe3, 0x83, 0x84, 0x29, 0x5f, 0x2f, 0xc2, 0xaf, 0x27, 0x20, 0x26, 0x26,
577 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x20, 0x31, 0x07,
578 ];
579 let mut dispatcher = Dispatcher::default();
580 let mut parser = Parser::new();
581
582 for byte in INPUT {
583 parser.advance(&mut dispatcher, *byte);
584 }
585
586 assert_eq!(dispatcher.dispatched.len(), 1);
587 match &dispatcher.dispatched[0] {
588 Sequence::Osc(params, _) => {
589 assert_eq!(params[0], &[b'2']);
590 assert_eq!(params[1], &INPUT[5..(INPUT.len() - 1)]);
591 },
592 _ => panic!("expected osc sequence"),
593 }
594 }
595
596 #[test]
597 fn osc_containing_string_terminator() {
598 static INPUT: &[u8] = b"\x1b]2;\xe6\x9c\xab\x1b\\";
599 let mut dispatcher = Dispatcher::default();
600 let mut parser = Parser::new();
601
602 for byte in INPUT {
603 parser.advance(&mut dispatcher, *byte);
604 }
605
606 assert_eq!(dispatcher.dispatched.len(), 2);
607 match &dispatcher.dispatched[0] {
608 Sequence::Osc(params, _) => {
609 assert_eq!(params[1], &INPUT[4..(INPUT.len() - 2)]);
610 },
611 _ => panic!("expected osc sequence"),
612 }
613 }
614
615 #[test]
616 fn exceed_max_buffer_size() {
617 static NUM_BYTES: usize = MAX_OSC_RAW + 100;
618 static INPUT_START: &[u8] = &[0x1b, b']', b'5', b'2', b';', b's'];
619 static INPUT_END: &[u8] = &[b'\x07'];
620
621 let mut dispatcher = Dispatcher::default();
622 let mut parser = Parser::new();
623
624 for byte in INPUT_START {
626 parser.advance(&mut dispatcher, *byte);
627 }
628
629 for _ in 0..NUM_BYTES {
631 parser.advance(&mut dispatcher, b'a');
632 }
633
634 for byte in INPUT_END {
636 parser.advance(&mut dispatcher, *byte);
637 }
638
639 assert_eq!(dispatcher.dispatched.len(), 1);
640 match &dispatcher.dispatched[0] {
641 Sequence::Osc(params, _) => {
642 assert_eq!(params.len(), 2);
643 assert_eq!(params[0], b"52");
644
645 #[cfg(not(feature = "no_std"))]
646 assert_eq!(params[1].len(), NUM_BYTES + INPUT_END.len());
647
648 #[cfg(feature = "no_std")]
649 assert_eq!(params[1].len(), MAX_OSC_RAW - params[0].len());
650 },
651 _ => panic!("expected osc sequence"),
652 }
653 }
654
655 #[test]
656 fn parse_csi_max_params() {
657 let params = "1;".repeat(params::MAX_PARAMS - 1);
661 let input = format!("\x1b[{}p", ¶ms[..]).into_bytes();
662
663 let mut dispatcher = Dispatcher::default();
664 let mut parser = Parser::new();
665
666 for byte in input {
667 parser.advance(&mut dispatcher, byte);
668 }
669
670 assert_eq!(dispatcher.dispatched.len(), 1);
671 match &dispatcher.dispatched[0] {
672 Sequence::Csi(params, _, ignore, _) => {
673 assert_eq!(params.len(), params::MAX_PARAMS);
674 assert!(!ignore);
675 },
676 _ => panic!("expected csi sequence"),
677 }
678 }
679
680 #[test]
681 fn parse_csi_params_ignore_long_params() {
682 let params = "1;".repeat(params::MAX_PARAMS);
686 let input = format!("\x1b[{}p", ¶ms[..]).into_bytes();
687
688 let mut dispatcher = Dispatcher::default();
689 let mut parser = Parser::new();
690
691 for byte in input {
692 parser.advance(&mut dispatcher, byte);
693 }
694
695 assert_eq!(dispatcher.dispatched.len(), 1);
696 match &dispatcher.dispatched[0] {
697 Sequence::Csi(params, _, ignore, _) => {
698 assert_eq!(params.len(), params::MAX_PARAMS);
699 assert!(ignore);
700 },
701 _ => panic!("expected csi sequence"),
702 }
703 }
704
705 #[test]
706 fn parse_csi_params_trailing_semicolon() {
707 let mut dispatcher = Dispatcher::default();
708 let mut parser = Parser::new();
709
710 for byte in b"\x1b[4;m" {
711 parser.advance(&mut dispatcher, *byte);
712 }
713
714 assert_eq!(dispatcher.dispatched.len(), 1);
715 match &dispatcher.dispatched[0] {
716 Sequence::Csi(params, ..) => assert_eq!(params, &[[4], [0]]),
717 _ => panic!("expected csi sequence"),
718 }
719 }
720
721 #[test]
722 fn parse_csi_params_leading_semicolon() {
723 let mut dispatcher = Dispatcher::default();
725 let mut parser = Parser::new();
726
727 for byte in b"\x1b[;4m" {
728 parser.advance(&mut dispatcher, *byte);
729 }
730
731 assert_eq!(dispatcher.dispatched.len(), 1);
732 match &dispatcher.dispatched[0] {
733 Sequence::Csi(params, ..) => assert_eq!(params, &[[0], [4]]),
734 _ => panic!("expected csi sequence"),
735 }
736 }
737
738 #[test]
739 fn parse_long_csi_param() {
740 static INPUT: &[u8] = b"\x1b[9223372036854775808m";
742 let mut dispatcher = Dispatcher::default();
743 let mut parser = Parser::new();
744
745 for byte in INPUT {
746 parser.advance(&mut dispatcher, *byte);
747 }
748
749 assert_eq!(dispatcher.dispatched.len(), 1);
750 match &dispatcher.dispatched[0] {
751 Sequence::Csi(params, ..) => assert_eq!(params, &[[std::u16::MAX as u16]]),
752 _ => panic!("expected csi sequence"),
753 }
754 }
755
756 #[test]
757 fn csi_reset() {
758 static INPUT: &[u8] = b"\x1b[3;1\x1b[?1049h";
759 let mut dispatcher = Dispatcher::default();
760 let mut parser = Parser::new();
761
762 for byte in INPUT {
763 parser.advance(&mut dispatcher, *byte);
764 }
765
766 assert_eq!(dispatcher.dispatched.len(), 1);
767 match &dispatcher.dispatched[0] {
768 Sequence::Csi(params, intermediates, ignore, _) => {
769 assert_eq!(intermediates, &[b'?']);
770 assert_eq!(params, &[[1049]]);
771 assert!(!ignore);
772 },
773 _ => panic!("expected csi sequence"),
774 }
775 }
776
777 #[test]
778 fn csi_subparameters() {
779 static INPUT: &[u8] = b"\x1b[38:2:255:0:255;1m";
780 let mut dispatcher = Dispatcher::default();
781 let mut parser = Parser::new();
782
783 for byte in INPUT {
784 parser.advance(&mut dispatcher, *byte);
785 }
786
787 assert_eq!(dispatcher.dispatched.len(), 1);
788 match &dispatcher.dispatched[0] {
789 Sequence::Csi(params, intermediates, ignore, _) => {
790 assert_eq!(params, &[vec![38, 2, 255, 0, 255], vec![1]]);
791 assert_eq!(intermediates, &[]);
792 assert!(!ignore);
793 },
794 _ => panic!("expected csi sequence"),
795 }
796 }
797
798 #[test]
799 fn parse_dcs_max_params() {
800 let params = "1;".repeat(params::MAX_PARAMS + 1);
801 let input = format!("\x1bP{}p", ¶ms[..]).into_bytes();
802 let mut dispatcher = Dispatcher::default();
803 let mut parser = Parser::new();
804
805 for byte in input {
806 parser.advance(&mut dispatcher, byte);
807 }
808
809 assert_eq!(dispatcher.dispatched.len(), 1);
810 match &dispatcher.dispatched[0] {
811 Sequence::DcsHook(params, _, ignore, _) => {
812 assert_eq!(params.len(), params::MAX_PARAMS);
813 assert!(params.iter().all(|param| param == &[1]));
814 assert!(ignore);
815 },
816 _ => panic!("expected dcs sequence"),
817 }
818 }
819
820 #[test]
821 fn dcs_reset() {
822 static INPUT: &[u8] = b"\x1b[3;1\x1bP1$tx\x9c";
823 let mut dispatcher = Dispatcher::default();
824 let mut parser = Parser::new();
825
826 for byte in INPUT {
827 parser.advance(&mut dispatcher, *byte);
828 }
829
830 assert_eq!(dispatcher.dispatched.len(), 3);
831 match &dispatcher.dispatched[0] {
832 Sequence::DcsHook(params, intermediates, ignore, _) => {
833 assert_eq!(intermediates, &[b'$']);
834 assert_eq!(params, &[[1]]);
835 assert!(!ignore);
836 },
837 _ => panic!("expected dcs sequence"),
838 }
839 assert_eq!(dispatcher.dispatched[1], Sequence::DcsPut(b'x'));
840 assert_eq!(dispatcher.dispatched[2], Sequence::DcsUnhook);
841 }
842
843 #[test]
844 fn parse_dcs() {
845 static INPUT: &[u8] = b"\x1bP0;1|17/ab\x9c";
846 let mut dispatcher = Dispatcher::default();
847 let mut parser = Parser::new();
848
849 for byte in INPUT {
850 parser.advance(&mut dispatcher, *byte);
851 }
852
853 assert_eq!(dispatcher.dispatched.len(), 7);
854 match &dispatcher.dispatched[0] {
855 Sequence::DcsHook(params, _, _, c) => {
856 assert_eq!(params, &[[0], [1]]);
857 assert_eq!(c, &'|');
858 },
859 _ => panic!("expected dcs sequence"),
860 }
861 for (i, byte) in b"17/ab".iter().enumerate() {
862 assert_eq!(dispatcher.dispatched[1 + i], Sequence::DcsPut(*byte));
863 }
864 assert_eq!(dispatcher.dispatched[6], Sequence::DcsUnhook);
865 }
866
867 #[test]
868 fn intermediate_reset_on_dcs_exit() {
869 static INPUT: &[u8] = b"\x1bP=1sZZZ\x1b+\x5c";
870 let mut dispatcher = Dispatcher::default();
871 let mut parser = Parser::new();
872
873 for byte in INPUT {
874 parser.advance(&mut dispatcher, *byte);
875 }
876
877 assert_eq!(dispatcher.dispatched.len(), 6);
878 match &dispatcher.dispatched[5] {
879 Sequence::Esc(intermediates, ..) => assert_eq!(intermediates, &[b'+']),
880 _ => panic!("expected esc sequence"),
881 }
882 }
883
884 #[test]
885 fn esc_reset() {
886 static INPUT: &[u8] = b"\x1b[3;1\x1b(A";
887 let mut dispatcher = Dispatcher::default();
888 let mut parser = Parser::new();
889
890 for byte in INPUT {
891 parser.advance(&mut dispatcher, *byte);
892 }
893
894 assert_eq!(dispatcher.dispatched.len(), 1);
895 match &dispatcher.dispatched[0] {
896 Sequence::Esc(intermediates, ignore, byte) => {
897 assert_eq!(intermediates, &[b'(']);
898 assert_eq!(*byte, b'A');
899 assert!(!ignore);
900 },
901 _ => panic!("expected esc sequence"),
902 }
903 }
904
905 #[test]
906 fn params_buffer_filled_with_subparam() {
907 static INPUT: &[u8] = b"\x1b[::::::::::::::::::::::::::::::::x\x1b";
908 let mut dispatcher = Dispatcher::default();
909 let mut parser = Parser::new();
910
911 for byte in INPUT {
912 parser.advance(&mut dispatcher, *byte);
913 }
914
915 assert_eq!(dispatcher.dispatched.len(), 1);
916 match &dispatcher.dispatched[0] {
917 Sequence::Csi(params, intermediates, ignore, c) => {
918 assert_eq!(intermediates, &[]);
919 assert_eq!(params, &[[0; 32]]);
920 assert_eq!(c, &'x');
921 assert!(ignore);
922 },
923 _ => panic!("expected csi sequence"),
924 }
925 }
926}
927
928#[cfg(all(feature = "nightly", test))]
929mod bench {
930 extern crate std;
931 extern crate test;
932
933 use super::*;
934
935 use test::{black_box, Bencher};
936
937 static VTE_DEMO: &[u8] = include_bytes!("../tests/demo.vte");
938
939 struct BenchDispatcher;
940 impl Perform for BenchDispatcher {
941 fn print(&mut self, c: char) {
942 black_box(c);
943 }
944
945 fn execute(&mut self, byte: u8) {
946 black_box(byte);
947 }
948
949 fn hook(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: char) {
950 black_box((params, intermediates, ignore, c));
951 }
952
953 fn put(&mut self, byte: u8) {
954 black_box(byte);
955 }
956
957 fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) {
958 black_box((params, bell_terminated));
959 }
960
961 fn csi_dispatch(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: char) {
962 black_box((params, intermediates, ignore, c));
963 }
964
965 fn esc_dispatch(&mut self, intermediates: &[u8], ignore: bool, byte: u8) {
966 black_box((intermediates, ignore, byte));
967 }
968 }
969
970 #[bench]
971 fn testfile(b: &mut Bencher) {
972 b.iter(|| {
973 let mut dispatcher = BenchDispatcher;
974 let mut parser = Parser::new();
975
976 for byte in VTE_DEMO {
977 parser.advance(&mut dispatcher, *byte);
978 }
979 });
980 }
981
982 #[bench]
983 fn state_changes(b: &mut Bencher) {
984 let input = b"\x1b]2;X\x1b\\ \x1b[0m \x1bP0@\x1b\\";
985 b.iter(|| {
986 let mut dispatcher = BenchDispatcher;
987 let mut parser = Parser::new();
988
989 for _ in 0..1_000 {
990 for byte in input {
991 parser.advance(&mut dispatcher, *byte);
992 }
993 }
994 });
995 }
996}