vt_push_parser/
event.rs

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        // Invalid duplicate intermediate
52        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        // Inefficient
79        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    // Plain printable text from GROUND (coalesced)
150    Raw(&'a [u8]),
151
152    // C0 control (EXECUTE)
153    C0(u8),
154
155    // ESC final (with intermediates)
156    Esc {
157        intermediates: VTIntermediate,
158        final_byte: u8,
159    },
160
161    // SS2
162    Ss2 {
163        char: u8,
164    },
165
166    // SS3
167    Ss3 {
168        char: u8,
169    },
170
171    // CSI short escape
172    Csi {
173        private: Option<u8>,
174        params: ParamBuf<'a>,
175        intermediates: VTIntermediate,
176        final_byte: u8,
177    },
178
179    // DCS stream
180    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    // OSC stream
191    OscStart,
192    OscData(&'a [u8]),
193    OscEnd {
194        /// Whether the BEL was used to end the OSC stream.
195        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    /// Encode the event into the provided buffer, returning the number of bytes
382    /// required for the escape sequence in either `Ok(n)` or `Err(n)`.
383    ///
384    /// Note that some events may have multiple possible encodings, so this method
385    /// may decide to choose whichever is more efficient.
386    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}